diff --git a/.github/ISSUE_TEMPLATE/00-bug-performance-issue.md b/.github/ISSUE_TEMPLATE/00-bug-performance-issue.md
new file mode 100644
index 0000000000000000000000000000000000000000..34ba4cf96017bb0dc15e74eee5d6ce211cf1058d
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/00-bug-performance-issue.md
@@ -0,0 +1,34 @@
+---
+name: Bug/Performance Issue
+about: Use this template for reporting a bug or a performance issue.
+
+---
+
+Please make sure that this is a bug. As per our [GitHub Policy](https://github.com/tensorflow/tensorflow/blob/master/ISSUES.md), we only address code/doc bugs, performance issues, feature requests and build/installation issues on GitHub. tag:bug_template
+
+**System information**
+- Have I written custom code (as opposed to using a stock example script provided in TensorFlow):
+- OS Platform and Distribution (e.g., Linux Ubuntu 16.04):
+- Mobile device (e.g. iPhone 8, Pixel 2, Samsung Galaxy) if the issue happens on mobile device:
+- TensorFlow installed from (source or binary):
+- TensorFlow version (use command below):
+- Python version:
+- Bazel version (if compiling from source):
+- GCC/Compiler version (if compiling from source):
+- CUDA/cuDNN version:
+- GPU model and memory:
+
+
+You can collect some of this information using our environment capture [script](https://github.com/tensorflow/tensorflow/tree/master/tools/tf_env_collect.sh)
+You can also obtain the TensorFlow version with
+python -c "import tensorflow as tf; print(tf.GIT_VERSION, tf.VERSION)"
+
+**Describe the current behavior**
+
+**Describe the expected behavior**
+
+**Code to reproduce the issue**
+Provide a reproducible test case that is the bare minimum necessary to generate the problem.
+
+**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/.github/ISSUE_TEMPLATE/10-build-installation-issue.md b/.github/ISSUE_TEMPLATE/10-build-installation-issue.md
new file mode 100644
index 0000000000000000000000000000000000000000..99c2fe61271fb51cce8aaf94d06d9d4a633aede4
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/10-build-installation-issue.md
@@ -0,0 +1,29 @@
+---
+name: Build/Installation Issue
+about: Use this template for build/installation issues
+
+---
+
+Please make sure that this is a build/installation issue. As per our [GitHub Policy](https://github.com/tensorflow/tensorflow/blob/master/ISSUES.md), we only address code/doc bugs, performance issues, feature requests and build/installation issues on GitHub. tag:build_template
+
+**System information**
+- OS Platform and Distribution (e.g., Linux Ubuntu 16.04):
+- Mobile device (e.g. iPhone 8, Pixel 2, Samsung Galaxy) if the issue happens on mobile device:
+- TensorFlow installed from (source or binary):
+- TensorFlow version:
+- Python version:
+- Installed using virtualenv? pip? conda?:
+- Bazel version (if compiling from source):
+- GCC/Compiler version (if compiling from source):
+- CUDA/cuDNN version:
+- GPU model and memory:
+
+
+
+**Describe the problem**
+
+**Provide the exact sequence of commands / steps that you executed before running into the problem**
+
+
+**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/.github/ISSUE_TEMPLATE/20-documentation-issue.md b/.github/ISSUE_TEMPLATE/20-documentation-issue.md
new file mode 100644
index 0000000000000000000000000000000000000000..7123ca6d6c507315dd3470e1813ac9dd17ba8fcd
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/20-documentation-issue.md
@@ -0,0 +1,17 @@
+---
+name: Documentation Issue
+about: Use this template for documentation related issues
+
+---
+
+Please make sure that this is a documentation issue. As per our [GitHub Policy](https://github.com/tensorflow/tensorflow/blob/master/ISSUES.md), we only address code/doc bugs, performance issues, feature requests and build/installation issues on GitHub. tag:doc_template
+
+
+**System information**
+- TensorFlow version:
+- Doc Link:
+
+
+**Describe the documentation issue**
+
+**We welcome contributions by users. Will you be able to update submit a PR (use the [doc style guide](https://www.tensorflow.org/community/documentation)) to fix the doc Issue?**
diff --git a/.github/ISSUE_TEMPLATE/30-feature-request.md b/.github/ISSUE_TEMPLATE/30-feature-request.md
new file mode 100644
index 0000000000000000000000000000000000000000..71df2e5e49f9e42a23a8c453da5335cfbbbb6211
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/30-feature-request.md
@@ -0,0 +1,22 @@
+---
+name: Feature Request
+about: Use this template for raising a feature request
+
+---
+
+Please make sure that this is a feature request. As per our [GitHub Policy](https://github.com/tensorflow/tensorflow/blob/master/ISSUES.md), we only address code/doc bugs, performance issues, feature requests and build/installation issues on GitHub. tag:feature_template
+
+
+**System information**
+- TensorFlow version (you are using):
+- Are you willing to contribute it (Yes/No):
+
+
+
+**Describe the feature and the current behavior/state.**
+
+**Will this change the current api? How?**
+
+**Who will benefit with this feature?**
+
+**Any Other info.**
diff --git a/.github/ISSUE_TEMPLATE/50-other-issues.md b/.github/ISSUE_TEMPLATE/50-other-issues.md
new file mode 100644
index 0000000000000000000000000000000000000000..2d78d9818bb69ebc7b0807afe5297051494c991e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/50-other-issues.md
@@ -0,0 +1,13 @@
+---
+name: Other Issues
+about: Use this template for any other non-support related issues
+
+---
+
+This template is for miscellaneous issues not covered by the other issue categories.
+
+For questions on how to work with TensorFlow, or support for problems that are not verified bugs in TensorFlow, please go to [StackOverflow](https://stackoverflow.com/questions/tagged/tensorflow).
+
+If you are reporting a vulnerability, please use the [dedicated reporting process](https://github.com/tensorflow/tensorflow/blob/master/SECURITY.md).
+
+For high-level discussions about TensorFlow, please post to discuss@tensorflow.org, for questions about the development or internal workings of TensorFlow, or if you would like to know how to contribute to TensorFlow, please post to developers@tensorflow.org.
diff --git a/.gitignore b/.gitignore
index cb65f447d4a551266e237714a16d71b58bcfc51d..90324058600bee46af56e49028977971848a80de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
.DS_Store
.ipynb_checkpoints
node_modules
+/.bazelrc
/.tf_configure.bazelrc
/bazel-*
/bazel_pip
@@ -23,10 +24,10 @@ Pods
Podfile.lock
*.pbxproj
*.xcworkspacedata
-/tensorflow/contrib/lite/downloads/**
-/tensorflow/contrib/lite/gen/**
-/tensorflow/contrib/lite/examples/ios/simple/data/*.txt
-/tensorflow/contrib/lite/examples/ios/simple/data/*.tflite
+/tensorflow/lite/tools/make/downloads/**
+/tensorflow/lite/gen/**
+/tensorflow/lite/examples/ios/simple/data/*.txt
+/tensorflow/lite/examples/ios/simple/data/*.tflite
xcuserdata/**
/api_init_files_list.txt
/estimator_api_init_files_list.txt
diff --git a/BUILD b/BUILD
index 4bf647e47aa56cff0b3fd5af7d5df99d8b70549b..1200cf5f7103cad12ab9693c339c372f4f3bc0fb 100644
--- a/BUILD
+++ b/BUILD
@@ -2,5 +2,7 @@ exports_files(
[
"LICENSE",
"ACKNOWLEDGEMENTS",
+ "configure",
+ "configure.py",
],
)
diff --git a/CODEOWNERS b/CODEOWNERS
index 94cc865479cd6ab5cdb589490d3a2d650f06b160..54a61a4d72c40d297d90d53e223f64f813d9167d 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -1,6 +1,7 @@
# Where component owners are known, add them here.
/tenosrflow/core/debug @caisq
+/tensorflow/core/nccl/ @azaks @csigg
/tensorflow/core/platform/windows/ @mrry
/tensorflow/core/platform/s3 @yongtang
/tensorflow/go @asimshankar
@@ -46,7 +47,6 @@
/tensorflow/contrib/losses/ @alextp @ispirmustafa
/tensorflow/contrib/makefile/ @petewarden @satok16 @wolffg
/tensorflow/contrib/metrics/ @alextp @honkentuber @ispirmustafa
-/tensorflow/contrib/nccl/ @cwhipkey @zheng-xq
/tensorflow/contrib/opt/ @strategist333 @alextp
/tensorflow/contrib/pi_examples/ @maciekcc
/tensorflow/contrib/quantization/ @petewarden
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 5fff9d05a1c589636bc9c711e6eb7cc4aba86b2f..a4647020ff76830badd75f3d3f76a41a637159bb 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -7,19 +7,22 @@ In the interest of fostering an open and welcoming environment, we as contributo
Examples of behavior that contributes to creating a positive environment include:
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
+* Using welcoming and inclusive language.
+* Being respectful of differing viewpoints and experiences.
+* Gracefully accepting constructive criticism.
+* Focusing on what is best for the community.
+* Showing empathy towards other community members.
Examples of unacceptable behavior by participants include:
-* The use of sexualized language or imagery and unwelcome sexual attention or advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic address, without explicit permission
-* Conduct which could reasonably be considered inappropriate for the forum in which it occurs.
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances.
+* Trolling, insulting/derogatory comments, and personal or political attacks.
+* Public or private harassment.
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission.
+* Conduct which could reasonably be considered inappropriate for the forum in
+ which it occurs.
All TensorFlow forums and spaces are meant for professional interactions, and any behavior which could reasonably be considered inappropriate in a professional setting is unacceptable.
@@ -48,10 +51,12 @@ However, for the vast majority of issues, we aim to empower individuals to first
If you are experiencing or witnessing conflict, we ask you to use the following escalation strategy to address the conflict:
-1. Address the perceived conflict directly with those involved, preferably in a real-time medium.
-2. If this fails, get a third party (e.g. a mutual friend, and/or someone with background on the issue, but not involved in conflict) to intercede.
-3. If you are still unable to resolve the conflict, and you believe it rises to harassment or another code of conduct violation, report it.
-
+1. Address the perceived conflict directly with those involved, preferably in a
+ real-time medium.
+2. If this fails, get a third party (e.g. a mutual friend, and/or someone with
+ background on the issue, but not involved in the conflict) to intercede.
+3. If you are still unable to resolve the conflict, and you believe it rises to
+ harassment or another code of conduct violation, report it.
## Reporting Violations
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f598999f351c10f8bd01dfbd3ad8897f19d570e8..4a296f265f7b9521c46d350cec26ff199f43eb6c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -31,8 +31,12 @@ Follow either of the two links above to access the appropriate CLA and instructi
If you have improvements to TensorFlow, send us your pull requests! For those
just getting started, Github has a [howto](https://help.github.com/articles/using-pull-requests/).
-TensorFlow team members will be assigned to review your pull requests. Once the pull requests are approved and pass continuous integration checks, we will merge the pull requests.
-For some pull requests, we will apply the patch for each pull request to our internal version control system first, and export the change out as a new commit later, at which point the original pull request will be closed. The commits in the pull request will be squashed into a single commit with the pull request creator as the author. These pull requests will be labeled as pending merge internally.
+TensorFlow team members will be assigned to review your pull requests. Once the
+pull requests are approved and pass continuous integration checks, a TensorFlow
+team member will apply `ready to pull` label to your change. This means we are
+working on getting your pull request submitted to our internal repository. After
+the change has been submitted internally, your pull request will be merged
+automatically on GitHub.
If you want to contribute but you're not sure where to start, take a look at the
[issues with the "contributions welcome" label](https://github.com/tensorflow/tensorflow/labels/stat%3Acontributions%20welcome).
diff --git a/ISSUES.md b/ISSUES.md
new file mode 100644
index 0000000000000000000000000000000000000000..2b330e8e0a8a3f64753cfb7a2e2362222439312d
--- /dev/null
+++ b/ISSUES.md
@@ -0,0 +1,9 @@
+If you open a GitHub Issue, here is our policy: 1. It must be a bug/performance
+issue or a feature request or a build issue or a documentation issue (for small
+doc fixes please send a PR instead). 2. Make sure the Issue Template is filled
+out. 3. The issue should be related to the repo it is created in.
+
+**Here's why we have this policy:** We want to focus on the work that benefits
+the whole community, e.g., fixing bugs and adding features. Individual support
+should be seeked on StackOverflow or other non-GitHub channels. It helps us to
+address bugs and feature requests in a timely manner.
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
index 52faed9297cfcaf8c93bb9c79686c9258a53c560..b3d84ad8c948df9459a8e8afb029785d6f6ad335 100644
--- a/ISSUE_TEMPLATE.md
+++ b/ISSUE_TEMPLATE.md
@@ -29,9 +29,11 @@ You can collect some of this information using our environment capture script:
https://github.com/tensorflow/tensorflow/tree/master/tools/tf_env_collect.sh
-You can obtain the TensorFlow version with
+You can obtain the TensorFlow version with:
+```bash
python -c "import tensorflow as tf; print(tf.GIT_VERSION, tf.VERSION)"
+```
### Describe the problem
Describe the problem clearly here. Be sure to convey here why it's a bug in TensorFlow or a feature request.
diff --git a/README.md b/README.md
index 57efb876c9afaf9fe76c4ced4e6a1572e9241edf..8af5370befbb090966a8b3af54d80c84a969aaa5 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,21 @@ subscribing to
[announce@tensorflow.org](https://groups.google.com/a/tensorflow.org/forum/#!forum/announce).
## Installation
-*See [Installing TensorFlow](https://www.tensorflow.org/install) for instructions on how to install our release binaries or how to build from source.*
+
+To install the current release for CPU-only:
+
+```
+pip install tensorflow
+```
+
+Use the GPU package for CUDA-enabled GPU cards:
+
+```
+pip install tensorflow-gpu
+```
+
+*See [Installing TensorFlow](https://www.tensorflow.org/install) for detailed
+instructions, and how to build from source.*
People who are a little more adventurous can also try our nightly binaries:
@@ -65,9 +79,10 @@ guidelines](CONTRIBUTING.md). This project adheres to TensorFlow's
uphold this code.**
**We use [GitHub issues](https://github.com/tensorflow/tensorflow/issues) for
-tracking requests and bugs. So please see
-[TensorFlow Discuss](https://groups.google.com/a/tensorflow.org/forum/#!forum/discuss) for general questions
-and discussion, and please direct specific questions to [Stack Overflow](https://stackoverflow.com/questions/tagged/tensorflow).**
+tracking requests and bugs, so please see
+[TensorFlow Discuss](https://groups.google.com/a/tensorflow.org/forum/#!forum/discuss)
+for general questions and discussion, and please direct specific questions to
+[Stack Overflow](https://stackoverflow.com/questions/tagged/tensorflow).**
The TensorFlow project strives to abide by generally accepted best practices in open-source software development:
@@ -93,14 +108,14 @@ The TensorFlow project strives to abide by generally accepted best practices in
### Community Supported Builds
-| Build Type | Status | Artifacts |
-| --- | --- | --- |
-| **IBM s390x** | [](http://ibmz-ci.osuosl.org/job/TensorFlow_IBMZ_CI/) | TBA |
-| **IBM ppc64le CPU** | [](http://powerci.osuosl.org/job/TensorFlow_Ubuntu_16.04_CPU/) | TBA |
-| **IBM ppc64le GPU** | [](http://powerci.osuosl.org/job/TensorFlow_Ubuntu_16.04_PPC64LE_GPU/) | TBA |
-| **Linux CPU with Intel® MKL-DNN** Nightly | [](https://tensorflow-ci.intel.com/job/tensorflow-mkl-linux-cpu/) | [Nightly](https://tensorflow-ci.intel.com/job/tensorflow-mkl-build-whl-nightly/) |
-| **Linux CPU with Intel® MKL-DNN** Python 2.7
**Linux CPU with Intel® MKL-DNN** Python 3.5
**Linux CPU with Intel® MKL-DNN** Python 3.6 | [](https://tensorflow-ci.intel.com/job/tensorflow-mkl-build-release-whl/lastStableBuild)|[1.10.0 py2.7](https://storage.googleapis.com/intel-optimized-tensorflow/tensorflow-1.10.0-cp27-cp27mu-linux_x86_64.whl)
[1.10.0 py3.5](https://storage.googleapis.com/intel-optimized-tensorflow/tensorflow-1.10.0-cp35-cp35m-linux_x86_64.whl)
[1.10.0 py3.6](https://storage.googleapis.com/intel-optimized-tensorflow/tensorflow-1.10.0-cp36-cp36m-linux_x86_64.whl) |
-
+Build Type | Status | Artifacts
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------
+**IBM s390x** | [](http://ibmz-ci.osuosl.org/job/TensorFlow_IBMZ_CI/) | TBA
+**IBM ppc64le CPU** | [](http://powerci.osuosl.org/job/TensorFlow_Ubuntu_16.04_CPU/) | TBA
+**IBM ppc64le GPU** Nightly | [](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 | [](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 | [](https://tensorflow-ci.intel.com/job/tensorflow-mkl-linux-cpu/) | [Nightly](https://tensorflow-ci.intel.com/job/tensorflow-mkl-build-whl-nightly/)
+**Linux CPU with Intel® MKL-DNN** Python 2.7
**Linux CPU with Intel® MKL-DNN** Python 3.4
**Linux CPU with Intel® MKL-DNN** Python 3.5
**Linux CPU with Intel® MKL-DNN** Python 3.6 | [](https://tensorflow-ci.intel.com/job/tensorflow-mkl-build-release-whl/lastStableBuild) | [1.11.0 py2.7](https://storage.googleapis.com/intel-optimized-tensorflow/tensorflow-1.11.0-cp27-cp27mu-linux_x86_64.whl)
[1.11.0 py3.4](https://storage.googleapis.com/intel-optimized-tensorflow/tensorflow-1.11.0-cp34-cp34m-linux_x86_64.whl)
[1.11.0 py3.5](https://storage.googleapis.com/intel-optimized-tensorflow/tensorflow-1.11.0-cp35-cp35m-linux_x86_64.whl)
[1.11.0 py3.6](https://storage.googleapis.com/intel-optimized-tensorflow/tensorflow-1.11.0-cp36-cp36m-linux_x86_64.whl)
## For more information
* [TensorFlow Website](https://www.tensorflow.org)
diff --git a/RELEASE.md b/RELEASE.md
index 20e1d9217b7684e696d0abf427eef9ab9548d1b7..b13b071bd6cf4d3a260c8e248a67d23e1a688498 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -1,3 +1,74 @@
+# Release 1.12.0
+
+## Major Features and Improvements
+
+* Keras models can now be directly exported to the SavedModel
+ format(`tf.contrib.saved_model.save_keras_model()`) and used with Tensorflow
+ Serving.
+* Keras models now support evaluating with a `tf.data.Dataset`.
+* TensorFlow binaries are built with XLA support linked in by default.
+
+## Bug Fixes and Other Changes
+
+* tf.data:
+ * tf.data users can now represent, get, and set options of TensorFlow
+ input pipelines using `tf.data.Options()`, `tf.data.Dataset.options()`,
+ and `tf.data.Dataset.with_options()` respectively.
+ * New `tf.data.Dataset.reduce()` API allows users to reduce a finite
+ dataset to a single element using a user-provided reduce function.
+ * New `tf.data.Dataset.window()` API allows users to create finite windows
+ of input dataset; when combined with the `tf.data.Dataset.reduce()` API,
+ this allows users to implement customized batching.
+ * All C++ code moves to the `tensorflow::data` namespace.
+ * Add support for `num_parallel_calls` to `tf.data.Dataset.interleave`.
+* `tf.contrib`:
+ * Remove `tf.contrib.linalg`. `tf.linalg` should be used instead.
+ * Replace any calls to `tf.contrib.get_signature_def_by_key(metagraph_def,
+ signature_def_key)` with
+ `meta_graph_def.signature_def[signature_def_key]`. Catching a ValueError
+ exception thrown by `tf.contrib.get_signature_def_by_key` should be
+ replaced by catching a KeyError exception.
+* `tf.contrib.data`
+ * Deprecate, and replace by tf.data.experimental.
+* Other:
+ * Instead of jemalloc, revert back to using system malloc since it
+ simplifies build and has comparable performance.
+ * Remove integer types from `tf.nn.softplus` and `tf.nn.softsign` OpDefs.
+ This is a bugfix; these ops were never meant to support integers.
+ * Allow subslicing Tensors with a single dimension.
+ * Add option to calculate string length in Unicode characters
+ * Add functionality to SubSlice a tensor.
+ * Add searchsorted (ie lower/upper_bound) op.
+ * Add model explainability to Boosted Trees.
+ * Support negative positions for tf.substr
+ * There was previously a bug in the bijector_impl where the
+ _reduce_jacobian_det_over_event does not handle scalar ILDJ
+ implementations properly.
+ * In tf eager execution, allow re-entering a GradientTape context
+ * Add tf_api_version flag. If --define=tf_api_version=2 flag is passed in,
+ then bazel will build TensorFlow API version 2.0. Note that TensorFlow
+ 2.0 is under active development and has no guarantees at this point.
+ * Add additional compression options to TfRecordWriter
+ * Performance improvements for regex full match operations.
+ * Replace tf.GraphKeys.VARIABLES with `tf.GraphKeys.GLOBAL_VARIABLES`
+ * Remove unused dynamic learning rate support.
+
+## Thanks to our Contributors
+
+This release contains contributions from many people at Google, as well as:
+
+(David) Siu-Kei Muk, Ag Ramesh, Anton Dmitriev, Artem Sobolev, Avijit-Nervana,
+Bairen Yi, Bruno Goncalves, By Shen, candy.dc, Cheng Chen, Clayne Robison,
+coder3101, Dao Zhang, Elms, Fei Hu, feiquan, Geoffrey Irving, Guozhong Zhuang,
+hellcom, Hoeseong Kim, imsheridan, Jason Furmanek, Jason Zaman, Jenny Sahng,
+jiefangxuanyan, Johannes Bannhofer, Jonathan Homer, Koan-Sin Tan, kouml, Loo
+Rong Jie, Lukas Geiger, manipopopo, Ming Li, Moritz KröGer, Naurril, Niranjan
+Hasabnis, Pan Daoxin, Peng Yu, pengwa, rasmi, Roger Xin, Roland Fernandez, Sami
+Kama, Samuel Matzek, Sangjung Woo, Sergei Lebedev, Sergii Khomenko, shaohua,
+Shaohua Zhang, Shujian2015, Sunitha Kambhampati, tomguluson92, ViníCius Camargo,
+wangsiyu, weidankong, Wen-Heng (Jack) Chung, William D. Irons, Xin Jin, Yan
+Facai (颜发才), Yanbo Liang, Yash Katariya, Yong Tang, 在原佐为
+
# Release 1.11.0
## Major Features and Improvements
@@ -20,51 +91,84 @@
## Bug Fixes and Other Changes
-* C++:
- * Changed the signature of SessionFactory::NewSession so that it can return a meaningful error message on failure.
-* tf.data:
- * Remove `num_parallel_parser_calls` argument from `tf.contrib.data.make_csv_dataset()`. [tf.data] Remove `num_parallel_parser_calls` argument from `tf.contrib.data.make_csv_dataset()`.
- * `tf.data.Dataset.list_files()` raises an exception at initialization time if the argument matches no files.
- * Renamed BigTable class to BigtableTable for clarity
- * Document use of the Cloud Bigtable API
- * Adding `tf.contrib.data.reduce_dataset` which can be used to reduce a dataset to a single element.
- * Generalization of `tf.contrib.data.sliding_window_batch`.
-* INC:
- * Runtime improvements to triangular solve.
-* `tf.contrib`:
- * Add an `implementation` argument to `tf.keras.layers.LocallyConnected2D` and `tf.keras.layers.LocallyConnected1D`. The new mode (`implementation=2`) performs forward pass as a single dense matrix multiplication, allowing dramatic speedups in certain scenarios (but worse performance in others - see docstring). The option also allows to use `padding=same`.
- * Add documentation clarifying the differences between tf.fill and tf.constant.
- * Add experimental IndexedDatasets.
- * Add selective registration target using the lite proto runtime.
- * Add simple Tensor and DataType classes to TensorFlow Lite Java
- * Add support for bitcasting to/from uint32 and uint64.
- * Added a subclass of Estimator that can be created from a SavedModel (SavedModelEstimator).
- * Adds leaf index modes as an argument.
- * Allow a different output shape from the input in tf.contrib.image.transform.
- * Change the state_size order of the StackedRNNCell to be natural order. To keep the existing behavior, user can add reverse_state_order=True when constructing the StackedRNNCells.
- * Deprecate self.test_session() in favor of self.session() or self.cached_session().
- * Directly import tensor.proto.h (the transitive import will be removed from tensor.h soon)
- * Estimator.train() now supports tf.contrib.summary.\* summaries out of the box; each call to .train() will now create a separate tfevents file rather than re-using a shared one.
- * Fix FTRL L2-shrinkage behavior: the gradient from the L2 shrinkage term should not end up in the accumulator.
- * Fix toco compilation/execution on Windows
- * GoogleZoneProvider class added to detect which Google Cloud Engine zone tensorflow is running in.
- * It is now safe to call any of the C API's TF_Delete\* functions on nullptr
- * Log some errors on Android to logcat
- * Match FakeQuant numerics in TFLite to improve accuracy of TFLite quantized inference models.
- * Optional bucket location check for the GCS Filesystem.
- * Performance enhancements for StringSplitOp & StringSplitV2Op.
- * Performance improvements for regex replace operations.
- * TFRecordWriter now raises an error if .write() fails.
- * TPU: More helpful error messages in TPUClusterResolvers.
- * The legacy_init_op argument to SavedModelBuilder methods for adding MetaGraphs has been deprecated. Please use the equivalent main_op argument instead. As part of this, we now explicitly check for a single main_op or legacy_init_op at the time of SavedModel building, whereas the check on main_op was previously only done at load time.
- * The protocol used for Estimator training is now configurable in RunConfig.
- * Triangular solve performance improvements.
- * Unify RNN cell interface between TF and Keras. Add new get_initial_state() to Keras and TF RNN cell, which will use to replace the existing zero_state() method.
- * Update initialization of variables in Keras.
- * Updates to "constrained_optimization" in tensorflow/contrib.
- * boosted trees: adding pruning mode
- * tf.train.Checkpoint does not delete old checkpoints by default.
- * tfdbg: Limit the total disk space occupied by dumped tensor data to 100 GBytes. Add environment variable `TFDBG_DISK_BYTES_LIMIT` to allow adjustment of this upper limit.
+* C++:
+ * Changed the signature of SessionFactory::NewSession so that it can
+ return a meaningful error message on failure.
+* tf.data:
+ * Remove `num_parallel_parser_calls` argument from
+ `tf.contrib.data.make_csv_dataset()`. [tf.data] Remove
+ `num_parallel_parser_calls` argument from
+ `tf.contrib.data.make_csv_dataset()`.
+ * `tf.data.Dataset.list_files()` raises an exception at initialization
+ time if the argument matches no files.
+ * Renamed BigTable class to BigtableTable for clarity
+ * Document use of the Cloud Bigtable API
+ * Add `tf.contrib.data.reduce_dataset` which can be used to reduce a
+ dataset to a single element.
+ * Generalization of `tf.contrib.data.sliding_window_batch`.
+* INC:
+ * Runtime improvements to triangular solve.
+* `tf.contrib`:
+ * Add an `implementation` argument to `tf.keras.layers.LocallyConnected2D`
+ and `tf.keras.layers.LocallyConnected1D`. The new mode
+ (`implementation=2`) performs forward pass as a single dense matrix
+ multiplication, allowing dramatic speedups in certain scenarios (but
+ worse performance in others - see docstring). The option also allows to
+ use `padding=same`.
+ * Add documentation clarifying the differences between tf.fill and
+ tf.constant.
+ * Add experimental IndexedDatasets.
+ * Add selective registration target using the lite proto runtime.
+ * Add simple Tensor and DataType classes to TensorFlow Lite Java
+ * Add support for bitcasting to/from uint32 and uint64.
+ * Added a subclass of Estimator that can be created from a SavedModel
+ (SavedModelEstimator).
+ * Adds leaf index modes as an argument.
+ * Allow a different output shape from the input in
+ tf.contrib.image.transform.
+ * Change the state_size order of the StackedRNNCell to be natural order.
+ To keep the existing behavior, user can add reverse_state_order=True
+ when constructing the StackedRNNCells.
+ * Deprecate self.test_session() in favor of self.session() or
+ self.cached_session().
+ * Directly import tensor.proto.h (the transitive import will be removed
+ from tensor.h soon)
+ * Estimator.train() now supports tf.contrib.summary.\* summaries out of
+ the box; each call to .train() will now create a separate tfevents file
+ rather than re-using a shared one.
+ * Fix FTRL L2-shrinkage behavior: the gradient from the L2 shrinkage term
+ should not end up in the accumulator.
+ * Fix toco compilation/execution on Windows
+ * GoogleZoneProvider class added to detect which Google Cloud Engine zone
+ tensorflow is running in.
+ * It is now safe to call any of the C API's TF_Delete\* functions on
+ nullptr
+ * Log some errors on Android to logcat
+ * Match FakeQuant numerics in TFLite to improve accuracy of TFLite
+ quantized inference models.
+ * Optional bucket location check for the GCS Filesystem.
+ * Performance enhancements for StringSplitOp & StringSplitV2Op.
+ * Performance improvements for regex replace operations.
+ * TFRecordWriter now raises an error if .write() fails.
+ * TPU: More helpful error messages in TPUClusterResolvers.
+ * The legacy_init_op argument to SavedModelBuilder methods for adding
+ MetaGraphs has been deprecated. Please use the equivalent main_op
+ argument instead. As part of this, we now explicitly check for a single
+ main_op or legacy_init_op at the time of SavedModel building, whereas
+ the check on main_op was previously only done at load time.
+ * The protocol used for Estimator training is now configurable in
+ RunConfig.
+ * Triangular solve performance improvements.
+ * Unify RNN cell interface between TF and Keras. Add new
+ get_initial_state() to Keras and TF RNN cell, which will use to replace
+ the existing zero_state() method.
+ * Update initialization of variables in Keras.
+ * Updates to "constrained_optimization" in tensorflow/contrib.
+ * boosted trees: adding pruning mode
+ * tf.train.Checkpoint does not delete old checkpoints by default.
+ * tfdbg: Limit the total disk space occupied by dumped tensor data to 100
+ GBytes. Add environment variable `TFDBG_DISK_BYTES_LIMIT` to allow
+ adjustment of this upper limit.
## Thanks to our Contributors
@@ -154,8 +258,8 @@ Ag Ramesh, Alex Wiltschko, Alexander Pantyukhin, Amogh Mannekote, An Jiaoyang, A
* Update `tf.keras` to the Keras 2.1.6 API.
* Added [`tf.keras.layers.CuDNNGRU`](https://www.tensorflow.org/versions/r1.9/api_docs/python/tf/keras/layers/CuDNNGRU) and [`tf.keras.layers.CuDNNLSTM`](https://www.tensorflow.org/versions/r1.9/api_docs/python/tf/keras/layers/CuDNNLSTM) layers. [Try it](https://colab.sandbox.google.com/github/tensorflow/tensorflow/blob/master/tensorflow/contrib/eager/python/examples/nmt_with_attention/nmt_with_attention.ipynb?linkId=53292082).
* Adding support of core [feature columns](https://www.tensorflow.org/get_started/feature_columns) and [losses](https://www.tensorflow.org/api_docs/python/tf/losses) to [gradient boosted trees estimators](https://github.com/tensorflow/models/tree/master/official/boosted_trees).
-* The [python interface](https://www.tensorflow.org/versions/r1.9/api_docs/python/tf/contrib/lite)
- for the [TFLite Optimizing Converter](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/lite/toco/README.md)
+* The [python interface](https://www.tensorflow.org/versions/r1.9/api_docs/python/tf/lite)
+ for the [TFLite Optimizing Converter](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/toco/README.md)
has been expanded, and the command line interface (AKA: `toco`, `tflite_convert`) is once again
included in the standard `pip` installation.
* Improved data-loading and text processing with:
@@ -458,7 +562,7 @@ Yoni Tsafir, yordun, Yuan (Terry) Tang, Yuxin Wu, zhengdi, Zhengsheng Wei, 田
## Major Features And Improvements
* [Eager execution](https://github.com/tensorflow/tensorflow/tree/r1.5/tensorflow/contrib/eager)
preview version is now available.
-* [TensorFlow Lite](https://github.com/tensorflow/tensorflow/tree/r1.5/tensorflow/contrib/lite)
+* [TensorFlow Lite](https://github.com/tensorflow/tensorflow/tree/r1.5/tensorflow/lite)
dev preview is now available.
* CUDA 9.0 and cuDNN 7 support.
* Accelerated Linear Algebra (XLA):
@@ -805,7 +909,7 @@ See also [TensorBoard 0.1.4](https://github.com/tensorflow/tensorboard/releases/
* Adds tf.contrib.nn.rank_sampled_softmax_loss, a sampled-softmax variant that can improve rank loss.
* `tf.contrib.metrics`.{streaming_covariance,streaming_pearson_correlation} modified to return nan when they have seen less or equal to 1 unit of weight.
* Adds time series models to contrib. See contrib/timeseries/README.md for details.
-* Adds FULLY_CONNECTED Op to tensorflow/contrib/lite/schema.fbs
+* Adds FULLY_CONNECTED Op to tensorflow/lite/schema.fbs
## Known Issues
* Tensorflow_gpu compilation fails with Bazel 0.5.3.
diff --git a/WORKSPACE b/WORKSPACE
index 17961829a605c2d1f2d2ba86a7c30c47618c139b..0c7bc085b512b084b9470abe17326d7c119aa327 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -14,6 +14,33 @@ load("@io_bazel_rules_closure//closure:defs.bzl", "closure_repositories")
closure_repositories()
+http_archive(
+ name = "base_images_docker",
+ sha256 = "e2b1b7254270bb7605e814a9dbf6d1e4ae04a11136ff1714fbfdabe3f87f7cf9",
+ strip_prefix = "base-images-docker-12801524f867e657fbb5d1a74f31618aff181ac6",
+ urls = ["https://github.com/GoogleCloudPlatform/base-images-docker/archive/12801524f867e657fbb5d1a74f31618aff181ac6.tar.gz"],
+)
+
+http_archive(
+ name = "bazel_toolchains",
+ sha256 = "15b5858b1b5541ec44df31b94c3b8672815b31d71215a98398761ea9f4c4eedb",
+ strip_prefix = "bazel-toolchains-6200b238c9c2d137c0d9a7262c80cc71d98e692b",
+ urls = [
+ "https://github.com/bazelbuild/bazel-toolchains/archive/6200b238c9c2d137c0d9a7262c80cc71d98e692b.tar.gz",
+ ],
+)
+
+http_archive(
+ name = "io_bazel_rules_docker",
+ sha256 = "29d109605e0d6f9c892584f07275b8c9260803bf0c6fcb7de2623b2bedc910bd",
+ strip_prefix = "rules_docker-0.5.1",
+ urls = ["https://github.com/bazelbuild/rules_docker/archive/v0.5.1.tar.gz"],
+)
+
+load("//third_party/toolchains/preconfig/generate:workspace.bzl", "remote_config_workspace")
+
+remote_config_workspace()
+
# We must check the bazel version before trying to parse any other BUILD
# files, in case the parsing of those build files depends on the bazel
# version we require here.
@@ -79,3 +106,4 @@ new_http_archive(
"http://download.tensorflow.org/models/speech_commands_v0.01.zip",
],
)
+
diff --git a/configure.py b/configure.py
index 65b46229955261abf923a7f2d41552ce249094a0..234561d94a46f57c4de5ca487360e2d5a3dfdb2f 100644
--- a/configure.py
+++ b/configure.py
@@ -43,7 +43,7 @@ _DEFAULT_CUDA_PATH_WIN = ('C:/Program Files/NVIDIA GPU Computing '
_TF_OPENCL_VERSION = '1.2'
_DEFAULT_COMPUTECPP_TOOLKIT_PATH = '/usr/local/computecpp'
_DEFAULT_TRISYCL_INCLUDE_DIR = '/usr/local/triSYCL/include'
-_SUPPORTED_ANDROID_NDK_VERSIONS = [10, 11, 12, 13, 14, 15, 16]
+_SUPPORTED_ANDROID_NDK_VERSIONS = [10, 11, 12, 13, 14, 15, 16, 17, 18]
_DEFAULT_PROMPT_ASK_ATTEMPTS = 10
@@ -383,7 +383,9 @@ def set_build_var(environ_cp,
var = str(int(get_var(environ_cp, var_name, query_item, enabled_by_default)))
environ_cp[var_name] = var
if var == '1':
- write_to_bazelrc('build --define %s=true' % option_name)
+ write_to_bazelrc(
+ 'build:%s --define %s=true' % (bazel_config_name, option_name))
+ write_to_bazelrc('build --config=%s' % bazel_config_name)
elif bazel_config_name is not None:
# TODO(mikecase): Migrate all users of configure.py to use --config Bazel
# options and not to set build configs through environment variables.
@@ -495,7 +497,7 @@ def set_cc_opt_flags(environ_cp):
elif is_windows():
default_cc_opt_flags = '/arch:AVX'
else:
- default_cc_opt_flags = '-march=native'
+ default_cc_opt_flags = '-march=native -Wno-sign-compare'
question = ('Please specify optimization flags to use during compilation when'
' bazel option "--config=opt" is specified [Default is %s]: '
) % default_cc_opt_flags
@@ -1180,6 +1182,7 @@ def set_tf_nccl_install_path(environ_cp):
if is_windows() or is_cygwin():
nccl_install_path = cygpath(nccl_install_path)
+ nccl_lib_path = ''
if is_windows():
nccl_lib_path = 'lib/x64/nccl.lib'
elif is_linux():
@@ -1415,11 +1418,16 @@ def set_mpi_home(environ_cp):
def valid_mpi_path(mpi_home):
exists = (
os.path.exists(os.path.join(mpi_home, 'include')) and
- os.path.exists(os.path.join(mpi_home, 'lib')))
+ (os.path.exists(os.path.join(mpi_home, 'lib')) or
+ os.path.exists(os.path.join(mpi_home, 'lib64')) or
+ os.path.exists(os.path.join(mpi_home, 'lib32'))))
if not exists:
- print('Invalid path to the MPI Toolkit. %s or %s cannot be found' %
- (os.path.join(mpi_home, 'include'),
- os.path.exists(os.path.join(mpi_home, 'lib'))))
+ print(
+ 'Invalid path to the MPI Toolkit. %s or %s or %s or %s cannot be found'
+ % (os.path.join(mpi_home, 'include'),
+ os.path.exists(os.path.join(mpi_home, 'lib')),
+ os.path.exists(os.path.join(mpi_home, 'lib64')),
+ os.path.exists(os.path.join(mpi_home, 'lib32'))))
return exists
_ = prompt_loop_or_load_from_env(
@@ -1460,8 +1468,17 @@ def set_other_mpi_vars(environ_cp):
if os.path.exists(os.path.join(mpi_home, 'lib/libmpi.so')):
symlink_force(
os.path.join(mpi_home, 'lib/libmpi.so'), 'third_party/mpi/libmpi.so')
+ elif os.path.exists(os.path.join(mpi_home, 'lib64/libmpi.so')):
+ symlink_force(
+ os.path.join(mpi_home, 'lib64/libmpi.so'), 'third_party/mpi/libmpi.so')
+ elif os.path.exists(os.path.join(mpi_home, 'lib32/libmpi.so')):
+ symlink_force(
+ os.path.join(mpi_home, 'lib32/libmpi.so'), 'third_party/mpi/libmpi.so')
+
else:
- raise ValueError('Cannot find the MPI library file in %s/lib' % mpi_home)
+ raise ValueError(
+ 'Cannot find the MPI library file in %s/lib or %s/lib64 or %s/lib32' %
+ mpi_home, mpi_home, mpi_home)
def set_system_libs_flag(environ_cp):
@@ -1496,14 +1513,6 @@ def set_windows_build_flags(environ_cp):
# TODO(pcloudy): Remove this flag when upgrading Bazel to 0.16.0
# Short object file path will be enabled by default.
write_to_bazelrc('build --experimental_shortened_obj_file_path=true')
- # When building zip file for some py_binary and py_test targets, don't
- # include its dependencies. This is for:
- # 1. Running python tests against the system installed TF pip package.
- # 2. Avoiding redundant files in
- # //tensorflow/tools/pip_package:simple_console_windows,
- # which is a py_binary used during creating TF pip package.
- # See https://github.com/tensorflow/tensorflow/issues/22390
- write_to_bazelrc('build --define=no_tensorflow_py_deps=true')
if get_var(
environ_cp, 'TF_OVERRIDE_EIGEN_STRONG_INLINE', 'Eigen strong inline',
@@ -1546,6 +1555,9 @@ def main():
check_bazel_version('0.15.0')
reset_tf_configure_bazelrc()
+ # Explicitly import tools/bazel.rc, this is needed for Bazel 0.19.0 or later
+ write_to_bazelrc('import %workspace%/tools/bazel.rc')
+
cleanup_makefile()
setup_python(environ_cp)
@@ -1558,13 +1570,11 @@ def main():
# TODO(ibiryukov): Investigate using clang as a cpu or cuda compiler on
# Windows.
environ_cp['TF_DOWNLOAD_CLANG'] = '0'
- environ_cp['TF_ENABLE_XLA'] = '0'
environ_cp['TF_NEED_MPI'] = '0'
environ_cp['TF_SET_ANDROID_WORKSPACE'] = '0'
if is_macos():
environ_cp['TF_NEED_TENSORRT'] = '0'
- environ_cp['TF_ENABLE_XLA'] = '0'
# The numpy package on ppc64le uses OpenBLAS which has multi-threading
# issues that lead to incorrect answers. Set OMP_NUM_THREADS=1 at
@@ -1573,10 +1583,9 @@ def main():
if is_ppc64le():
write_action_env_to_bazelrc('OMP_NUM_THREADS', 1)
- set_build_var(environ_cp, 'TF_NEED_IGNITE', 'Apache Ignite',
- 'with_ignite_support', True, 'ignite')
+ xla_enabled_by_default = is_linux()
set_build_var(environ_cp, 'TF_ENABLE_XLA', 'XLA JIT', 'with_xla_support',
- True, 'xla')
+ xla_enabled_by_default, 'xla')
set_action_env_var(environ_cp, 'TF_NEED_OPENCL_SYCL', 'OpenCL SYCL', False)
if environ_cp.get('TF_NEED_OPENCL_SYCL') == '1':
@@ -1668,18 +1677,23 @@ def main():
create_android_ndk_rule(environ_cp)
create_android_sdk_rule(environ_cp)
- # On Windows, we don't have MKL support and the build is always monolithic.
- # So no need to print the following message.
- # TODO(pcloudy): remove the following if check when they make sense on Windows
- if not is_windows():
- print('Preconfigured Bazel build configs. You can use any of the below by '
- 'adding "--config=<>" to your build command. See .bazelrc for more '
- 'details.')
- config_info_line('mkl', 'Build with MKL support.')
- config_info_line('monolithic', 'Config for mostly static monolithic build.')
- config_info_line('gdr', 'Build with GDR support.')
- config_info_line('verbs', 'Build with libverbs support.')
- config_info_line('ngraph', 'Build with Intel nGraph support.')
+ print('Preconfigured Bazel build configs. You can use any of the below by '
+ 'adding "--config=<>" to your build command. See .bazelrc for more '
+ 'details.')
+ config_info_line('mkl', 'Build with MKL support.')
+ config_info_line('monolithic', 'Config for mostly static monolithic build.')
+ config_info_line('gdr', 'Build with GDR support.')
+ config_info_line('verbs', 'Build with libverbs support.')
+ config_info_line('ngraph', 'Build with Intel nGraph support.')
+ config_info_line('dynamic_kernels',
+ '(Experimental) Build kernels into separate shared objects.')
+
+ print('Preconfigured Bazel build configs to DISABLE default on features:')
+ config_info_line('noaws', 'Disable AWS S3 filesystem support.')
+ config_info_line('nogcp', 'Disable GCP support.')
+ config_info_line('nohdfs', 'Disable HDFS support.')
+ config_info_line('noignite', 'Disable Apacha Ignite support.')
+ config_info_line('nokafka', 'Disable Apache Kafka support.')
if __name__ == '__main__':
diff --git a/tensorflow/BUILD b/tensorflow/BUILD
index 9b62a504525d5377d4836e92bdf0e46f7fc3ef38..17577afecb74b7008db5a282255278b35ed138a6 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(
@@ -209,12 +214,40 @@ config_setting(
visibility = ["//visibility:public"],
)
+# Features that are default ON are handled differently below.
+#
+config_setting(
+ name = "no_aws_support",
+ define_values = {"no_aws_support": "true"},
+ visibility = ["//visibility:public"],
+)
+
+config_setting(
+ name = "no_gcp_support",
+ define_values = {"no_gcp_support": "true"},
+ visibility = ["//visibility:public"],
+)
+
+config_setting(
+ name = "no_hdfs_support",
+ define_values = {"no_hdfs_support": "true"},
+ visibility = ["//visibility:public"],
+)
+
+config_setting(
+ name = "no_ignite_support",
+ define_values = {"no_ignite_support": "true"},
+ visibility = ["//visibility:public"],
+)
+
config_setting(
- name = "with_ignite_support",
- define_values = {"with_ignite_support": "true"},
+ name = "no_kafka_support",
+ define_values = {"no_kafka_support": "true"},
visibility = ["//visibility:public"],
)
+# Crosses between platforms and file system libraries not supported on those
+# platforms due to limitations in nested select() statements.
config_setting(
name = "with_cuda_support_windows_override",
define_values = {"using_cuda_nvcc": "true"},
@@ -322,8 +355,9 @@ 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/...",
],
)
@@ -525,35 +559,45 @@ 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.__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_init_template = "api_template.__init__.py",
+ root_file_name = "v1.py",
+ root_init_template = "api_template_v1.__init__.py",
)
gen_api_init_files(
name = "tf_python_api_gen_v2",
- srcs = ["api_template.__init__.py"],
+ srcs = [
+ "api_template.__init__.py",
+ "compat_template_v1.__init__.py",
+ ],
api_version = 2,
compat_api_versions = [1],
+ compat_init_templates = ["compat_template_v1.__init__.py"],
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",
)
py_library(
name = "tensorflow_py",
- srcs = ["//tensorflow/python/estimator/api:estimator_python_api_gen"],
srcs_version = "PY2AND3",
visibility = ["//visibility:public"],
deps = [
diff --git a/tensorflow/api_template.__init__.py b/tensorflow/api_template.__init__.py
index 2de740e145f93b151faf5c987808dbdf73fb4fd7..2efb8846c6837a3935e0a8439a18838cb2bea804 100644
--- a/tensorflow/api_template.__init__.py
+++ b/tensorflow/api_template.__init__.py
@@ -23,39 +23,25 @@ import os as _os
# pylint: disable=g-bad-import-order
from tensorflow.python import pywrap_tensorflow # pylint: disable=unused-import
-try:
- # Add `estimator` attribute to allow access to estimator APIs via
- # "tf.estimator..."
- from tensorflow.python.estimator.api import estimator # pylint: disable=g-import-not-at-top
-
- # Add `estimator` to the __path__ to allow "from tensorflow.estimator..."
- # style imports.
- from tensorflow.python.estimator import api as estimator_api # pylint: disable=g-import-not-at-top
- __path__ += [_os.path.dirname(estimator_api.__file__)]
- del estimator_api
-except (ImportError, AttributeError):
- print('tf.estimator package not installed.')
+from tensorflow.python.tools import component_api_helper as _component_api_helper
+_component_api_helper.package_hook(
+ parent_package_str=__name__,
+ child_package_str=('tensorflow_estimator.python.estimator.api.estimator'))
# API IMPORTS PLACEHOLDER
-from tensorflow.python.util.lazy_loader import LazyLoader # pylint: disable=g-import-not-at-top
-contrib = LazyLoader('contrib', globals(), 'tensorflow.contrib')
-del LazyLoader
-# The templated code that replaces the placeholder above sometimes
-# sets the __all__ variable. If it does, we have to be sure to add
-# "contrib".
-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
# 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
+
# These symbols appear because we import the python package which
# in turn imports from tensorflow.core and tensorflow.python. They
# must come from this module. So python adds these symbols for the
@@ -66,7 +52,14 @@ try:
del core
except NameError:
# Don't fail if these modules are not available.
- # For e.g. we are using this file for compat.v1 module as well and
- # 'python', 'core' directories are not under compat/v1.
+ # For e.g. this file will be originally placed under tensorflow/_api/v1 which
+ # does not have 'python', 'core' directories. Then, it will be copied
+ # to tensorflow/ which does have these two directories.
+ pass
+# Similarly for compiler. Do it separately to make sure we do this even if the
+# others don't exist.
+try:
+ del compiler
+except NameError:
pass
# pylint: enable=undefined-variable
diff --git a/tensorflow/api_template_v1.__init__.py b/tensorflow/api_template_v1.__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..65bdb6cb1b5e6fb0656a12b932d767aeacfccd29
--- /dev/null
+++ b/tensorflow/api_template_v1.__init__.py
@@ -0,0 +1,72 @@
+# 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.
+# ==============================================================================
+"""Bring in all of the public TensorFlow interface into this module."""
+
+from __future__ import absolute_import as _absolute_import
+from __future__ import division as _division
+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__,
+ child_package_str=('tensorflow_estimator.python.estimator.api.estimator'))
+
+# API IMPORTS PLACEHOLDER
+
+from tensorflow.python.util.lazy_loader import LazyLoader # pylint: disable=g-import-not-at-top
+contrib = LazyLoader('contrib', globals(), 'tensorflow.contrib')
+del LazyLoader
+# The templated code that replaces the placeholder above sometimes
+# sets the __all__ variable. If it does, we have to be sure to add
+# "contrib".
+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
+
+# 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
+if _tf_api_dir not in __path__:
+ __path__.append(_tf_api_dir)
+
+
+# These symbols appear because we import the python package which
+# in turn imports from tensorflow.core and tensorflow.python. They
+# must come from this module. So python adds these symbols for the
+# resolution to succeed.
+# pylint: disable=undefined-variable
+try:
+ del python
+ del core
+except NameError:
+ # Don't fail if these modules are not available.
+ # For e.g. this file will be originally placed under tensorflow/_api/v1 which
+ # does not have 'python', 'core' directories. Then, it will be copied
+ # to tensorflow/ which does have these two directories.
+ pass
+# Similarly for compiler. Do it separately to make sure we do this even if the
+# others don't exist.
+try:
+ del compiler
+except NameError:
+ pass
+# pylint: enable=undefined-variable
diff --git a/tensorflow/c/BUILD b/tensorflow/c/BUILD
index 17e2e292eb19029d279bc12a8328edadf96f1bb8..84238ffc1f2b73c59055461fbeba33687d756208 100644
--- a/tensorflow/c/BUILD
+++ b/tensorflow/c/BUILD
@@ -6,11 +6,12 @@ licenses(["notice"]) # Apache 2.0
load(
"//tensorflow:tensorflow.bzl",
"tf_cc_test",
- "tf_cuda_cc_test",
"tf_copts",
"tf_cuda_library",
"tf_custom_op_library",
+ "tf_kernel_library",
)
+load("//tensorflow:tensorflow.bzl", "tf_cuda_cc_test")
# -----------------------------------------------------------------------------
# Public targets
@@ -59,6 +60,7 @@ tf_cuda_library(
"//tensorflow/core:framework",
"//tensorflow/core:lib",
"//tensorflow/core:op_gen_lib",
+ "//tensorflow/core/distributed_runtime:server_lib",
],
}),
)
@@ -94,6 +96,7 @@ tf_cuda_library(
"//tensorflow/core:protos_all_cc",
"//tensorflow/core:lib",
"//tensorflow/core:lib_internal",
+ "//tensorflow/core/distributed_runtime:server_lib",
],
}) + select({
"//tensorflow:with_xla_support": [
@@ -118,13 +121,14 @@ tf_cuda_library(
":c_api",
":c_api_internal",
"//tensorflow/c/eager:c_api",
- "//tensorflow/compiler/jit/legacy_flags:mark_for_compilation_pass_flags",
+ "//tensorflow/compiler/jit:flags",
"//tensorflow/contrib/tpu:all_ops",
"//tensorflow/core:core_cpu",
"//tensorflow/core:framework",
"//tensorflow/core:lib",
"//tensorflow/core:lib_platform",
"//tensorflow/core:protos_all_cc",
+ "//tensorflow/core/common_runtime/eager:attr_builder",
],
)
@@ -170,6 +174,28 @@ 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",
+ "//tensorflow/core:android_tensorflow_lib_lite",
+ ],
+ "//conditions:default": [
+ ":c_api",
+ "//tensorflow/core:framework",
+ ],
+ }),
+)
+
# -----------------------------------------------------------------------------
# Tests
@@ -197,14 +223,18 @@ tf_cuda_cc_test(
size = "small",
srcs = ["c_api_test.cc"],
data = [
- ":test_op.so",
+ ":test_op1.so",
"//tensorflow/cc/saved_model:saved_model_half_plus_two",
],
+ kernels = [":test_op_kernel"],
linkopts = select({
"//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(),
@@ -215,6 +245,7 @@ tf_cuda_cc_test(
"//tensorflow/cc:grad_ops",
"//tensorflow/cc/saved_model:signature_constants",
"//tensorflow/cc/saved_model:tag_constants",
+ "//tensorflow/compiler/jit",
"//tensorflow/core:core_cpu_internal",
"//tensorflow/core:direct_session",
"//tensorflow/core:framework",
@@ -281,8 +312,42 @@ tf_cc_test(
)
tf_custom_op_library(
- name = "test_op.so",
+ name = "test_op1.so",
+ srcs = ["test_op1.cc"],
+)
+
+tf_kernel_library(
+ name = "test_op_kernel",
srcs = ["test_op.cc"],
+ deps = [
+ "//tensorflow/core:framework",
+ "//tensorflow/core:lib",
+ ],
+ 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",
+ ],
)
# -----------------------------------------------------------------------------
diff --git a/tensorflow/c/README.md b/tensorflow/c/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..b386998ceaf3e91daba04125fe83e2f3bdd508e5
--- /dev/null
+++ b/tensorflow/c/README.md
@@ -0,0 +1,7 @@
+# TensorFlow C API
+
+- See [www.tensorflow.org/install/lang_c](https://www.tensorflow.org/install/lang_c)
+- Nightly builds:
+ - [Linux CPU-only](https://storage.googleapis.com/tensorflow-nightly/github/tensorflow/lib_package/libtensorflow-cpu-linux-x86_64.tar.gz)
+ - [Linux GPU](https://storage.googleapis.com/tensorflow-nightly/github/tensorflow/lib_package/libtensorflow-gpu-linux-x86_64.tar.gz)
+ - [MacOS CPU-only](https://storage.googleapis.com/tensorflow-nightly/github/tensorflow/lib_package/libtensorflow-cpu-darwin-x86_64.tar.gz)
diff --git a/tensorflow/c/c_api.cc b/tensorflow/c/c_api.cc
index 79811ceae57e0bddeb2a6f32bad7003e14e23422..f13e8777dff164bcd8eedf46310ae846abd0c804 100644
--- a/tensorflow/c/c_api.cc
+++ b/tensorflow/c/c_api.cc
@@ -1942,6 +1942,10 @@ void TF_ImportGraphDefOptionsSetPrefix(TF_ImportGraphDefOptions* opts,
const char* prefix) {
opts->opts.prefix = prefix;
}
+void TF_ImportGraphDefOptionsSetDefaultDevice(TF_ImportGraphDefOptions* opts,
+ const char* device) {
+ opts->opts.default_device = device;
+}
void TF_ImportGraphDefOptionsSetUniquifyNames(TF_ImportGraphDefOptions* opts,
unsigned char uniquify_names) {
@@ -2770,6 +2774,9 @@ TF_Buffer* TF_ApiDefMapGet(TF_ApiDefMap* api_def_map, const char* name,
}
string name_str(name, name_len);
const auto* api_def = api_def_map->api_def_map.GetApiDef(name_str);
+ if (api_def == nullptr) {
+ return nullptr;
+ }
TF_Buffer* ret = TF_NewBuffer();
status->status = MessageToBuffer(*api_def, ret);
@@ -2803,4 +2810,71 @@ TF_Buffer* TF_GetRegisteredKernelsForOp(const char* name, TF_Status* status) {
}
return ret;
}
+
+// TF_Server functions ----------------------------------------------
+
+#ifndef __ANDROID__
+TF_Server::TF_Server(std::unique_ptr server)
+ : target(server->target()), server(std::move(server)) {}
+#endif // __ANDROID__
+
+TF_Server* TF_NewServer(const void* proto, size_t proto_len,
+ TF_Status* status) {
+#ifdef __ANDROID__
+ status->status = tensorflow::errors::Unimplemented(
+ "Server functionality is not supported in Android");
+ return nullptr;
+#else
+ tensorflow::ServerDef server_def;
+ if (!server_def.ParseFromArray(proto, static_cast(proto_len))) {
+ status->status = InvalidArgument(
+ "Could not parse provided bytes into a ServerDef protocol buffer");
+ return nullptr;
+ }
+
+ std::unique_ptr out_server;
+ status->status = tensorflow::NewServer(server_def, &out_server);
+ if (!status->status.ok()) return nullptr;
+
+ return new TF_Server(std::move(out_server));
+#endif
+}
+
+void TF_ServerStart(TF_Server* server, TF_Status* status) {
+#ifdef __ANDROID__
+ status->status = tensorflow::errors::Unimplemented(
+ "Server functionality is not supported in Android");
+#else
+ status->status = server->server->Start();
+#endif
+}
+
+void TF_ServerStop(TF_Server* server, TF_Status* status) {
+#ifdef __ANDROID__
+ status->status = tensorflow::errors::Unimplemented(
+ "Server functionality is not supported in Android");
+#else
+ status->status = server->server->Stop();
+#endif
+}
+
+void TF_ServerJoin(TF_Server* server, TF_Status* status) {
+#ifdef __ANDROID__
+ status->status = tensorflow::errors::Unimplemented(
+ "Server functionality is not supported in Android");
+#else
+ status->status = server->server->Join();
+#endif
+}
+
+const char* TF_ServerTarget(TF_Server* server) {
+#ifdef __ANDROID__
+ return nullptr;
+#else
+ return server->target.c_str();
+#endif
+}
+
+void TF_DeleteServer(TF_Server* server) { delete server; }
+
} // end extern "C"
diff --git a/tensorflow/c/c_api.h b/tensorflow/c/c_api.h
index 850f6ecd637d768bca99720e0add07680829e17a..3d56268110edbe96616201d15a69cc8c84d3115a 100644
--- a/tensorflow/c/c_api.h
+++ b/tensorflow/c/c_api.h
@@ -900,6 +900,12 @@ TF_CAPI_EXPORT extern void TF_DeleteImportGraphDefOptions(
TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsSetPrefix(
TF_ImportGraphDefOptions* opts, const char* prefix);
+// Set the execution device for nodes in `graph_def`.
+// Only applies to nodes where a device was not already explicitly specified.
+// `device` is copied and has no lifetime requirements.
+TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsSetDefaultDevice(
+ TF_ImportGraphDefOptions* opts, const char* device);
+
// Set whether to uniquify imported operation names. If true, imported operation
// names will be modified if their name already exists in the graph. If false,
// conflicting names will be treated as an error. Note that this option has no
@@ -1662,6 +1668,47 @@ TF_CAPI_EXPORT extern TF_Buffer* TF_GetAllRegisteredKernels(TF_Status* status);
TF_CAPI_EXPORT extern TF_Buffer* TF_GetRegisteredKernelsForOp(
const char* name, TF_Status* status);
+// --------------------------------------------------------------------------
+// In-process TensorFlow server functionality, for use in distributed training.
+// A Server instance encapsulates a set of devices and a Session target that
+// can participate in distributed training. A server belongs to a cluster
+// (specified by a ClusterSpec), and corresponds to a particular task in a
+// named job. The server can communicate with any other server in the same
+// cluster.
+
+// In-process TensorFlow server.
+typedef struct TF_Server TF_Server;
+
+// Creates a new in-process TensorFlow server configured using a serialized
+// ServerDef protocol buffer provided via `proto` and `proto_len`.
+//
+// The server will not serve any requests until TF_ServerStart is invoked.
+// The server will stop serving requests once TF_ServerStop or
+// TF_DeleteServer is invoked.
+TF_CAPI_EXPORT extern TF_Server* TF_NewServer(const void* proto,
+ size_t proto_len,
+ TF_Status* status);
+
+// Starts an in-process TensorFlow server.
+TF_CAPI_EXPORT extern void TF_ServerStart(TF_Server* server, TF_Status* status);
+
+// Stops an in-process TensorFlow server.
+TF_CAPI_EXPORT extern void TF_ServerStop(TF_Server* server, TF_Status* status);
+
+// Blocks until the server has been successfully stopped (via TF_ServerStop or
+// TF_ServerClose).
+TF_CAPI_EXPORT extern void TF_ServerJoin(TF_Server* server, TF_Status* status);
+
+// Returns the target string that can be provided to TF_SetTarget() to connect
+// a TF_Session to `server`.
+//
+// The returned string is valid only until TF_DeleteServer is invoked.
+TF_CAPI_EXPORT extern const char* TF_ServerTarget(TF_Server* server);
+
+// Destroy an in-process TensorFlow server, frees memory. If server is running
+// it will be stopped and joined.
+TF_CAPI_EXPORT extern void TF_DeleteServer(TF_Server* server);
+
#ifdef __cplusplus
} /* end extern "C" */
#endif
diff --git a/tensorflow/c/c_api_experimental.cc b/tensorflow/c/c_api_experimental.cc
index d4b78138e93624a7e41e917f8210281b500661bc..f160f204dec50b6495ed11c12c48918611206b01 100644
--- a/tensorflow/c/c_api_experimental.cc
+++ b/tensorflow/c/c_api_experimental.cc
@@ -16,11 +16,13 @@ limitations under the License.
#include "tensorflow/c/c_api_experimental.h"
#include "tensorflow/c/c_api_internal.h"
-#include "tensorflow/compiler/jit/legacy_flags/mark_for_compilation_pass_flags.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/platform.h"
#include "tensorflow/core/protobuf/config.pb.h"
#include "tensorflow/core/protobuf/tensorflow_server.pb.h"
@@ -50,8 +52,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 {
@@ -70,8 +72,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 {
@@ -8742,3 +8744,74 @@ TF_CAPI_EXPORT extern 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;
+};
+
+TF_AttrBuilder* TF_NewAttrBuilder(const char* op_name) {
+ return new TF_AttrBuilder(op_name);
+}
+
+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));
+}
+
+void TF_AttrBuilderSetTypeList(TF_AttrBuilder* builder, const char* attr_name,
+ const TF_DataType* values, int num_values) {
+ builder->Set(
+ attr_name,
+ tensorflow::gtl::ArraySlice(
+ reinterpret_cast(values), num_values));
+}
+
+void TF_AttrBuilderCheckCanRunOnDevice(TF_AttrBuilder* builder,
+ const char* device_type,
+ TF_Status* status) {
+ status->status = tensorflow::FindKernelDef(
+ tensorflow::DeviceType(device_type), builder->BuildNodeDef(),
+ /* def = */ nullptr, /* kernel_class_name = */ nullptr);
+}
+
+const char* TF_GetNumberAttrForOpListInput(const char* op_name, int input_index,
+ TF_Status* status) {
+ const tensorflow::OpDef* op_def = nullptr;
+ status->status =
+ tensorflow::OpRegistry::Global()->LookUpOpDef(op_name, &op_def);
+ if (!status->status.ok()) return nullptr;
+
+ if (input_index >= op_def->input_arg_size() || input_index < 0) {
+ status->status = tensorflow::errors::InvalidArgument(
+ input_index, " out of range for ", op_name);
+ return nullptr;
+ }
+
+ const tensorflow::OpDef_ArgDef& input_arg = op_def->input_arg()[input_index];
+
+ if (input_arg.number_attr().empty()) {
+ status->status = tensorflow::errors::NotFound(
+ op_name, " does not have number_attr() defined.");
+ return nullptr;
+ }
+
+ // 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);
+}
diff --git a/tensorflow/c/c_api_experimental.h b/tensorflow/c/c_api_experimental.h
index d98d532e32e891e21f5b7ba360c74c3256fb1947..25c03df51890a6a599528645aad6ed9ff5b49ff0 100644
--- a/tensorflow/c/c_api_experimental.h
+++ b/tensorflow/c/c_api_experimental.h
@@ -183,6 +183,41 @@ TF_CAPI_EXPORT extern void TFE_TensorHandlePrintDebugString(
TF_CAPI_EXPORT extern void TF_MakeInternalErrorStatus(TF_Status* status,
const char* errMsg);
+// TF_NewAttrBuilder() returns an object that you can set attributes on as
+// though it were an op. This allows querying properties of that op for
+// type-checking purposes like if the op will run on a particular device type.
+typedef struct TF_AttrBuilder TF_AttrBuilder;
+TF_CAPI_EXPORT extern TF_AttrBuilder* TF_NewAttrBuilder(const char* op_name);
+TF_CAPI_EXPORT extern void TF_DeleteAttrBuilder(TF_AttrBuilder* builder);
+TF_CAPI_EXPORT extern void TF_AttrBuilderSetType(TF_AttrBuilder* builder,
+ const char* attr_name,
+ TF_DataType value);
+TF_CAPI_EXPORT extern void TF_AttrBuilderSetTypeList(TF_AttrBuilder* builder,
+ const char* attr_name,
+ const TF_DataType* values,
+ int num_values);
+
+// Checks the tensorflow::NodeDef built via the methods above to see if it can
+// run on device_type.
+TF_CAPI_EXPORT extern void TF_AttrBuilderCheckCanRunOnDevice(
+ TF_AttrBuilder* builder, const char* device_type, TF_Status* status);
+
+// For argument number input_index, fetch the corresponding number_attr that
+// needs to be updated with the argument length of the input list.
+// Returns nullptr if there is any problem like op_name is not found, or the
+// argument does not support this attribute type.
+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);
+
#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 c6effd39697e0397278770b53e98508074f99862..881dbaf35a5ec470a7e359312e33c4a27752a727 100644
--- a/tensorflow/c/c_api_experimental_test.cc
+++ b/tensorflow/c/c_api_experimental_test.cc
@@ -162,5 +162,16 @@ 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);
+}
+
} // namespace
} // namespace tensorflow
diff --git a/tensorflow/c/c_api_function.cc b/tensorflow/c/c_api_function.cc
index f68f8a3e90a971b5e4a024feaf26ba498afc48da..28b9f8df9c873ee394eb6a241dd9ac06ba6c8796 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/c_api_internal.h b/tensorflow/c/c_api_internal.h
index 95652a11378d6276b5ba6540a07baa15aa77cc1c..5ba26d3c585350aa510f9970cbfc246a9a108543 100644
--- a/tensorflow/c/c_api_internal.h
+++ b/tensorflow/c/c_api_internal.h
@@ -25,6 +25,7 @@ limitations under the License.
#include
#ifndef __ANDROID__
+#include "tensorflow/core/distributed_runtime/server_lib.h"
#include "tensorflow/core/framework/op_gen_lib.h"
#endif
#include "tensorflow/core/common_runtime/shape_refiner.h"
@@ -179,6 +180,15 @@ struct TF_ApiDefMap {
tensorflow::mutex lock;
};
+#ifndef __ANDROID__
+struct TF_Server {
+ TF_Server(std::unique_ptr server);
+
+ const tensorflow::string target;
+ std::unique_ptr server;
+};
+#endif
+
namespace tensorflow {
class TensorCApi {
diff --git a/tensorflow/c/c_api_test.cc b/tensorflow/c/c_api_test.cc
index 03516c39dc970aa23967107d3a0446da94669465..d5934a10395ae094f65d3bc8b6cd7b94dbd32410 100644
--- a/tensorflow/c/c_api_test.cc
+++ b/tensorflow/c/c_api_test.cc
@@ -33,6 +33,7 @@ limitations under the License.
#include "tensorflow/core/framework/node_def.pb_text.h"
#include "tensorflow/core/framework/node_def_util.h"
#include "tensorflow/core/framework/op.h"
+#include "tensorflow/core/framework/op_def.pb.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/partial_tensor_shape.h"
#include "tensorflow/core/framework/tensor.h"
@@ -186,23 +187,40 @@ TEST(CAPI, LibraryLoadFunctions) {
// tf_cuda_cc_test() bazel rule and remove the next line.
if (!GPUDeviceName().empty()) return;
- // Load the library.
- TF_Status* status = TF_NewStatus();
- TF_Library* lib =
- TF_LoadLibrary("tensorflow/c/test_op.so", status);
- TF_Code code = TF_GetCode(status);
- string status_msg(TF_Message(status));
- TF_DeleteStatus(status);
- ASSERT_EQ(TF_OK, code) << status_msg;
-
- // Test op list.
- TF_Buffer op_list_buf = TF_GetOpList(lib);
- tensorflow::OpList op_list;
- EXPECT_TRUE(op_list.ParseFromArray(op_list_buf.data, op_list_buf.length));
- ASSERT_EQ(op_list.op_size(), 1);
- EXPECT_EQ("TestCApi", op_list.op(0).name());
-
- TF_DeleteLibraryHandle(lib);
+#if !defined(TENSORFLOW_NO_SHARED_OBJECTS)
+ {
+ // Load the library.
+ TF_Status* status = TF_NewStatus();
+ TF_Library* lib =
+ TF_LoadLibrary("tensorflow/c/test_op1.so", status);
+ TF_Code code = TF_GetCode(status);
+ string status_msg(TF_Message(status));
+ TF_DeleteStatus(status);
+ ASSERT_EQ(TF_OK, code) << status_msg;
+
+ // Test op list.
+ TF_Buffer op_list_buf = TF_GetOpList(lib);
+ tensorflow::OpList op_list;
+ EXPECT_TRUE(op_list.ParseFromArray(op_list_buf.data, op_list_buf.length));
+ ASSERT_EQ(op_list.op_size(), 1);
+ EXPECT_EQ("TestCApi1", op_list.op(0).name());
+ TF_DeleteLibraryHandle(lib);
+ }
+#endif // !defined(TENSORFLOW_NO_SHARED_OBJECTS)
+ {
+ TF_Buffer* op_list_buffer = TF_GetAllOpList();
+ tensorflow::OpList op_list;
+ op_list.ParseFromArray(op_list_buffer->data, op_list_buffer->length);
+ ASSERT_GE(op_list.op_size(), 1);
+ typedef tensorflow::protobuf::RepeatedPtrField OpDefs;
+ const OpDefs& ops = op_list.op();
+ bool found = std::find_if(ops.begin(), ops.end(),
+ [](const tensorflow::OpDef& op_def) {
+ return op_def.name() == "TestCApi";
+ }) != ops.end();
+ EXPECT_TRUE(found);
+ TF_DeleteBuffer(op_list_buffer);
+ }
}
void TestEncodeDecode(int line, const std::vector& data) {
@@ -2329,15 +2347,9 @@ TEST(TestApiDef, TestCreateApiDef) {
// tf_cuda_cc_test() bazel rule and remove the next line.
if (!GPUDeviceName().empty()) return;
+ TF_Buffer* op_list_buf = TF_GetAllOpList();
TF_Status* status = TF_NewStatus();
- TF_Library* lib =
- TF_LoadLibrary("tensorflow/c/test_op.so", status);
- EXPECT_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status);
- TF_DeleteStatus(status);
-
- TF_Buffer op_list_buf = TF_GetOpList(lib);
- status = TF_NewStatus();
- auto* api_def_map = TF_NewApiDefMap(&op_list_buf, status);
+ auto* api_def_map = TF_NewApiDefMap(op_list_buf, status);
EXPECT_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status);
TF_DeleteStatus(status);
@@ -2355,7 +2367,7 @@ TEST(TestApiDef, TestCreateApiDef) {
TF_DeleteBuffer(api_def_buf);
TF_DeleteApiDefMap(api_def_map);
- TF_DeleteLibraryHandle(lib);
+ TF_DeleteBuffer(op_list_buf);
}
TEST(TestApiDef, TestCreateApiDefWithOverwrites) {
@@ -2363,15 +2375,9 @@ TEST(TestApiDef, TestCreateApiDefWithOverwrites) {
// tf_cuda_cc_test() bazel rule and remove the next line.
if (!GPUDeviceName().empty()) return;
+ TF_Buffer* op_list_buf = TF_GetAllOpList();
TF_Status* status = TF_NewStatus();
- TF_Library* lib =
- TF_LoadLibrary("tensorflow/c/test_op.so", status);
- EXPECT_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status);
- TF_DeleteStatus(status);
-
- TF_Buffer op_list_buf = TF_GetOpList(lib);
- status = TF_NewStatus();
- auto* api_def_map = TF_NewApiDefMap(&op_list_buf, status);
+ auto* api_def_map = TF_NewApiDefMap(op_list_buf, status);
EXPECT_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status);
TF_DeleteStatus(status);
@@ -2400,7 +2406,7 @@ TEST(TestApiDef, TestCreateApiDefWithOverwrites) {
TF_DeleteBuffer(api_def_buf);
TF_DeleteApiDefMap(api_def_map);
- TF_DeleteLibraryHandle(lib);
+ TF_DeleteBuffer(op_list_buf);
}
class DummyKernel : public tensorflow::OpKernel {
diff --git a/tensorflow/c/eager/BUILD b/tensorflow/c/eager/BUILD
index 3ee31a6a7ac641bbd3fc4c05568b61e433a1d523..ba3d8533db7623b8fa7fdf35093abcd1450776b1 100644
--- a/tensorflow/c/eager/BUILD
+++ b/tensorflow/c/eager/BUILD
@@ -69,7 +69,7 @@ tf_cuda_library(
name = "c_api_internal",
hdrs = ["c_api_internal.h"],
visibility = [
- "//learning/deepmind/courier:__pkg__",
+ "//learning/deepmind/courier:__subpackages__",
"//tensorflow:internal",
],
deps = [
diff --git a/tensorflow/c/eager/c_api.cc b/tensorflow/c/eager/c_api.cc
index 3554ec0bf3202b54bfc38d67e51b89df19832302..192044915f06e3644aebb200a229cce5f220752b 100755
--- a/tensorflow/c/eager/c_api.cc
+++ b/tensorflow/c/eager/c_api.cc
@@ -24,6 +24,7 @@ limitations under the License.
#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
@@ -404,8 +405,7 @@ const char* TFE_TensorHandleDeviceName(TFE_TensorHandle* h, TF_Status* status) {
"The passed in handle is a nullptr");
return nullptr;
}
- tensorflow::Device* d = nullptr;
- status->status = h->handle->OpDevice(&d);
+ tensorflow::Device* d = h->handle->op_device();
return (d == nullptr) ? "/job:localhost/replica:0/task:0/device:CPU:0"
: d->name().c_str();
}
@@ -459,13 +459,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;
}
@@ -498,12 +505,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_debug.cc b/tensorflow/c/eager/c_api_debug.cc
index 5006b76f1981d068e99a2c081115ebb3a66d8c7f..52b0824552855860dfb138f3ac9a5d3afa7dc965 100644
--- a/tensorflow/c/eager/c_api_debug.cc
+++ b/tensorflow/c/eager/c_api_debug.cc
@@ -57,13 +57,9 @@ TF_CAPI_EXPORT extern TFE_TensorDebugInfo* TFE_TensorHandleTensorDebugInfo(
return nullptr;
}
- tensorflow::Device* device;
- status->status = handle->handle->Device(&device);
- if (!status->status.ok()) {
- return nullptr;
- }
-
#ifdef TENSORFLOW_EAGER_USE_XLA
+ tensorflow::Device* device = handle->handle->device();
+
// If tensor resides on an XLA device, use XLA device's PaddedShapeFn.
tensorflow::XlaDevice* xla_device =
dynamic_cast(device);
diff --git a/tensorflow/c/eager/c_api_internal.h b/tensorflow/c/eager/c_api_internal.h
index 104d52430cf7aa14d4d2a335a1b96e667f21ce87..67bc1bcd24605f8363d6a7c8d5d6a0836a42fc82 100644
--- a/tensorflow/c/eager/c_api_internal.h
+++ b/tensorflow/c/eager/c_api_internal.h
@@ -79,10 +79,6 @@ struct TFE_TensorHandle {
tensorflow::Device* op_device)
: handle(new tensorflow::TensorHandle(t, d, op_device, nullptr)) {}
- TFE_TensorHandle(tensorflow::uint64 node_id, tensorflow::DataType dtype,
- tensorflow::EagerContext* ctx)
- : handle(new tensorflow::TensorHandle(node_id, dtype, ctx)) {}
-
TFE_TensorHandle(tensorflow::TensorHandle* handle) : handle(handle) {}
tensorflow::TensorHandle* handle;
@@ -97,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 55331022b9dbd0696928fa44430f340f371432ac..0045bb5622647974a3c9f2cdf35bc21e126b4f52 100644
--- a/tensorflow/c/eager/c_api_test.cc
+++ b/tensorflow/c/eager/c_api_test.cc
@@ -589,9 +589,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);
diff --git a/tensorflow/c/eager/tape.h b/tensorflow/c/eager/tape.h
index 5ba55a203ff70cc64c07e96b5a869a1f11c9334e..5c11f51e8749de84547ae873f5f55ebd42bc4b3d 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 0000000000000000000000000000000000000000..ca69345264607ac689fb556b4f5c9bc08ea5eb88
--- /dev/null
+++ b/tensorflow/c/kernels.cc
@@ -0,0 +1,118 @@
+/* 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/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, "");
+}
diff --git a/tensorflow/c/kernels.h b/tensorflow/c/kernels.h
new file mode 100644
index 0000000000000000000000000000000000000000..2518789a3c141755d0b3373d53642c487331f68b
--- /dev/null
+++ b/tensorflow/c/kernels.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_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);
+
+#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 0000000000000000000000000000000000000000..e706c7c1d96ee1781d8efc0f28c5e0cbcbc80861
--- /dev/null
+++ b/tensorflow/c/kernels_test.cc
@@ -0,0 +1,99 @@
+/* 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/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) {
+ LOG(INFO) << "Wow, actually got into creation";
+ 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;
+}
+
+// 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 = "barDev";
+
+ 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("FooOp", status);
+ EXPECT_EQ(TF_OK, TF_GetCode(status));
+ ::tensorflow::KernelList list;
+ list.ParseFromArray(buf->data, buf->length);
+ ASSERT_EQ(1, list.kernel_size());
+ ASSERT_EQ("barDev", list.kernel(0).device_type());
+ TF_DeleteBuffer(buf);
+ TF_DeleteStatus(status);
+ }
+
+ REGISTER_OP("FooOp")
+ .Input("input1: double")
+ .Input("input2: uint8")
+ .Output("output1: uint8");
+
+ {
+ ::tensorflow::NodeDef def;
+ def.set_op("FooOp");
+ def.set_device("bar");
+ def.add_input("input1");
+ def.add_input("input2");
+ ::tensorflow::Status status;
+ std::unique_ptr<::tensorflow::OpKernel> kernel =
+ ::tensorflow::CreateOpKernel(::tensorflow::DeviceType("barDev"),
+ nullptr, nullptr, def, 1, &status);
+ TF_EXPECT_OK(status);
+ ASSERT_NE(nullptr, kernel.get());
+ kernel->Compute(nullptr);
+ }
+
+ ASSERT_TRUE(delete_called);
+}
diff --git a/tensorflow/core/kernels/captured_function.h b/tensorflow/c/test_op1.cc
similarity index 68%
rename from tensorflow/core/kernels/captured_function.h
rename to tensorflow/c/test_op1.cc
index 2d2d87134e786139386509c6e5f353bb88882915..b22cc9aef2b344282f45340ff12ee849935a26f9 100644
--- a/tensorflow/core/kernels/captured_function.h
+++ b/tensorflow/c/test_op1.cc
@@ -1,4 +1,4 @@
-/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+/* 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.
@@ -12,9 +12,12 @@ WITHOUT 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_CAPTURED_FUNCTION_H_
-#define TENSORFLOW_CORE_KERNELS_CAPTURED_FUNCTION_H_
-#include "tensorflow/core/kernels/data/captured_function.h"
+#include "tensorflow/core/framework/op.h"
+#include "tensorflow/core/framework/op_kernel.h"
-#endif // TENSORFLOW_CORE_KERNELS_CAPTURED_FUNCTION_H_
+namespace tensorflow {
+
+REGISTER_OP("TestCApi1").Doc(R"doc(Used to test C API)doc");
+
+} // namespace tensorflow
diff --git a/tensorflow/cc/BUILD b/tensorflow/cc/BUILD
index b587e63227708427e7fae47f8f4a7b524d963ed9..83353b79f722f0a95f508b32d4a49b14b35624fb 100644
--- a/tensorflow/cc/BUILD
+++ b/tensorflow/cc/BUILD
@@ -170,6 +170,7 @@ cc_library_with_android_deps(
"//tensorflow/core:framework",
"//tensorflow/core:lib",
"//tensorflow/core:protos_all_cc",
+ "@com_google_absl//absl/strings",
],
)
@@ -411,6 +412,7 @@ tf_cc_test(
srcs = ["gradients/nn_grad_test.cc"],
deps = [
":cc_ops",
+ ":cc_ops_internal",
":grad_op_registry",
":grad_testutil",
":gradient_checker",
@@ -453,11 +455,33 @@ tf_cc_test(
],
)
+# Generates separate libraries for array_ops and math_ops to reduce the dependency count of targets that depend on only these
tf_gen_op_wrappers_cc(
- name = "cc_ops",
+ name = "math_ops",
+ api_def_srcs = ["//tensorflow/core/api_def:base_api_def"],
+ op_lib_names = [
+ "math_ops",
+ ],
+ pkg = "//tensorflow/core",
+)
+
+tf_gen_op_wrappers_cc(
+ name = "array_ops",
api_def_srcs = ["//tensorflow/core/api_def:base_api_def"],
op_lib_names = [
"array_ops",
+ ],
+ pkg = "//tensorflow/core",
+)
+
+tf_gen_op_wrappers_cc(
+ name = "cc_ops",
+ api_def_srcs = ["//tensorflow/core/api_def:base_api_def"],
+ deps_internal = [
+ ":array_ops_internal",
+ ":math_ops_internal",
+ ],
+ op_lib_names = [
"audio_ops",
"candidate_sampling_ops",
"control_flow_ops",
@@ -468,7 +492,6 @@ tf_gen_op_wrappers_cc(
"logging_ops",
"lookup_ops",
"manip_ops",
- "math_ops",
"nn_ops",
"no_op",
"parsing_ops",
@@ -480,10 +503,23 @@ tf_gen_op_wrappers_cc(
"user_ops",
],
other_hdrs = [
+ "ops/array_ops.h",
"ops/const_op.h",
+ "ops/math_ops.h",
"ops/standard_ops.h",
],
+ other_hdrs_internal = [
+ "ops/array_ops_internal.h",
+ "ops/math_ops_internal.h",
+ ],
pkg = "//tensorflow/core",
+ deps = [
+ ":array_ops",
+ ":const_op",
+ ":math_ops",
+ "//tensorflow/cc:ops",
+ "//tensorflow/cc:scope",
+ ],
)
tf_cc_test(
diff --git a/tensorflow/cc/framework/scope.cc b/tensorflow/cc/framework/scope.cc
index 6abc9e268e3ac97379954a34017ddffa010db67f..81785b2d89b3d36b46992b7ae376b5175a806027 100644
--- a/tensorflow/cc/framework/scope.cc
+++ b/tensorflow/cc/framework/scope.cc
@@ -95,6 +95,7 @@ Scope::Impl::Impl(const Scope& other, Tags::ScopeName, const string& name,
kernel_label_(other.impl()->kernel_label_),
device_(other.impl()->device_),
assigned_device_(other.impl()->assigned_device_),
+ xla_cluster_(other.impl()->xla_cluster_),
colocation_constraints_(other.impl()->colocation_constraints_),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
@@ -112,6 +113,7 @@ Scope::Impl::Impl(const Scope& other, Tags::OpName, const string& name,
kernel_label_(other.impl()->kernel_label_),
device_(other.impl()->device_),
assigned_device_(other.impl()->assigned_device_),
+ xla_cluster_(other.impl()->xla_cluster_),
colocation_constraints_(other.impl()->colocation_constraints_),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
@@ -135,6 +137,7 @@ Scope::Impl::Impl(const Scope& other, Tags::ControlDeps,
kernel_label_(other.impl()->kernel_label_),
device_(other.impl()->device_),
assigned_device_(other.impl()->assigned_device_),
+ xla_cluster_(other.impl()->xla_cluster_),
colocation_constraints_(other.impl()->colocation_constraints_),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
@@ -167,6 +170,7 @@ Scope::Impl::Impl(const Scope& other, Tags::SingleUseScope,
kernel_label_(other.impl()->kernel_label_),
device_(other.impl()->device_),
assigned_device_(other.impl()->assigned_device_),
+ xla_cluster_(other.impl()->xla_cluster_),
colocation_constraints_(other.impl()->colocation_constraints_),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
@@ -183,6 +187,7 @@ Scope::Impl::Impl(const Scope& other, Tags::ExitOnError)
kernel_label_(other.impl()->kernel_label_),
device_(other.impl()->device_),
assigned_device_(other.impl()->assigned_device_),
+ xla_cluster_(other.impl()->xla_cluster_),
colocation_constraints_(other.impl()->colocation_constraints_),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
@@ -200,6 +205,7 @@ Scope::Impl::Impl(const Scope& other, Tags::KernelLabel,
kernel_label_(kernel_label),
device_(other.impl()->device_),
assigned_device_(other.impl()->assigned_device_),
+ xla_cluster_(other.impl()->xla_cluster_),
colocation_constraints_(other.impl()->colocation_constraints_),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
@@ -217,6 +223,7 @@ Scope::Impl::Impl(const Scope& other, Tags::Colocate,
kernel_label_(other.impl()->kernel_label_),
device_(other.impl()->device_),
assigned_device_(other.impl()->assigned_device_),
+ xla_cluster_(other.impl()->xla_cluster_),
colocation_constraints_(
clear_colocations
? std::unordered_set()
@@ -237,6 +244,25 @@ Scope::Impl::Impl(const Scope& other, Tags::AssignedDevice,
kernel_label_(other.impl()->kernel_label_),
device_(other.impl()->device_),
assigned_device_(assigned_device),
+ xla_cluster_(other.impl()->xla_cluster_),
+ colocation_constraints_(other.impl()->colocation_constraints_),
+ disable_shape_inference_(other.impl()->disable_shape_inference_) {}
+
+Scope::Impl::Impl(const Scope& other, Tags::XlaCluster,
+ const string& xla_cluster)
+ : graph_(other.impl()->graph_),
+ status_(other.impl()->status_),
+ name_map_(other.impl()->name_map_),
+ refiner_(other.impl()->refiner_),
+ scope_used_(other.impl()->scope_used_),
+ control_deps_(other.impl()->control_deps_),
+ name_(other.impl()->name_),
+ op_name_(other.impl()->op_name_),
+ exit_on_error_(other.impl()->exit_on_error_),
+ kernel_label_(other.impl()->kernel_label_),
+ device_(other.impl()->device_),
+ assigned_device_(other.impl()->assigned_device_),
+ xla_cluster_(xla_cluster),
colocation_constraints_(other.impl()->colocation_constraints_),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
@@ -326,6 +352,9 @@ void Scope::UpdateBuilder(NodeBuilder* builder) const {
if (!impl()->assigned_device_.empty()) {
builder->AssignedDevice(impl()->assigned_device_);
}
+ if (!impl()->xla_cluster_.empty()) {
+ builder->XlaCluster(impl()->xla_cluster_);
+ }
}
string Scope::Impl::GetUniqueName(const string& prefix,
@@ -388,7 +417,7 @@ Scope Scope::NewSubScope(const string& child_scope_name) const {
false /* copy_names */));
}
-Scope Scope::WithOpName(const string& op_name) const {
+Scope Scope::WithOpNameImpl(const string& op_name) const {
if (impl()->single_use_scope()) {
UpdateStatus(errors::InvalidArgument("Cannot set op name ", op_name,
" on this scope"));
@@ -425,6 +454,10 @@ Scope Scope::WithAssignedDevice(const string& assigned_device) const {
return Scope(new Impl(*this, Impl::Tags::AssignedDevice(), assigned_device));
}
+Scope Scope::WithXlaCluster(const string& xla_cluster) const {
+ return Scope(new Impl(*this, Impl::Tags::XlaCluster(), xla_cluster));
+}
+
Scope Scope::ColocateWith(const Operation& op) const {
return Scope(new Impl(*this, Impl::Tags::Colocate(), op,
/* clear_colocations */ false));
diff --git a/tensorflow/cc/framework/scope.h b/tensorflow/cc/framework/scope.h
index e307d8989b6647dfac8d2691ed2171c86b7f3a7c..0a75f23725c143e6b22ee6dffae1428ed8209fe8 100644
--- a/tensorflow/cc/framework/scope.h
+++ b/tensorflow/cc/framework/scope.h
@@ -22,6 +22,7 @@ limitations under the License.
#include
#include
+#include "absl/strings/str_cat.h"
#include "tensorflow/cc/framework/ops.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/lib/gtl/array_slice.h"
@@ -69,8 +70,9 @@ struct CompositeOpScopes;
/// // W will be named "linear/W"
/// auto W = Variable(linear.WithOpName("W"),
/// {2, 2}, DT_FLOAT);
-/// // b will be named "linear/b"
-/// auto b = Variable(linear.WithOpName("b"),
+/// // b will be named "linear/b_3"
+/// int idx = 3;
+/// auto b = Variable(linear.WithOpName("b_", idx),
/// {2}, DT_FLOAT);
/// auto x = Const(linear, {...}); // name: "linear/Const"
/// auto m = MatMul(linear, x, W); // name: "linear/MatMul"
@@ -113,8 +115,11 @@ class Scope {
Scope NewSubScope(const string& child_scope_name) const;
/// Return a new scope. All ops created within the returned scope will have
- /// names of the form `name/op_name[_suffix]`.
- Scope WithOpName(const string& op_name) const;
+ /// names of the form `name/StrCat(fragments...)[_suffix]`
+ template
+ Scope WithOpName(Ty... fragments) const {
+ return WithOpNameImpl(absl::StrCat(fragments...));
+ }
/// Return a new scope. All ops created within the returned scope will have as
/// control dependencies the union of operations in the control_deps vector
@@ -137,6 +142,10 @@ class Scope {
/// their assigned device set to `assigned_device`.
Scope WithAssignedDevice(const string& assigned_device) const;
+ /// Returns a new scope. All ops created within the returned scope will have
+ /// their _XlaCluster attribute set to `xla_cluster`.
+ Scope WithXlaCluster(const string& xla_cluster) const;
+
/// Return a new scope. All ops created within the returned scope will be
/// co-located on the device where op is placed.
/// NOTE: This function is intended to be use internal libraries only for
@@ -227,6 +236,8 @@ class Scope {
// END_SKIP_DOXYGEN
private:
+ Scope WithOpNameImpl(const string& op_name) const;
+
friend class InternalScope;
std::unique_ptr impl_;
explicit Scope(Impl*);
diff --git a/tensorflow/cc/framework/scope_internal.h b/tensorflow/cc/framework/scope_internal.h
index 514e02e84146b6d95147d83182e5d9a07509cfa1..5db7eab2b819c2c5d8fc358953d4607848f1cba5 100644
--- a/tensorflow/cc/framework/scope_internal.h
+++ b/tensorflow/cc/framework/scope_internal.h
@@ -61,6 +61,7 @@ class Scope::Impl {
enum class KernelLabel;
enum class Colocate;
enum class AssignedDevice;
+ enum class XlaCluster;
};
Impl(Graph* graph, Status* status, NameMap* name_map, ShapeRefiner* refiner,
@@ -78,6 +79,7 @@ class Scope::Impl {
Impl(const Scope& other, Tags::Colocate, const Operation& colocate_with_op,
bool clear_colocations);
Impl(const Scope& other, Tags::AssignedDevice, const string& assigned_device);
+ Impl(const Scope& other, Tags::XlaCluster, const string& xla_cluster);
std::unordered_set GetColocationConstraints(
const Operation& colocate_with_op) const;
@@ -112,6 +114,7 @@ class Scope::Impl {
const string kernel_label_ = "";
const string device_ = "";
const string assigned_device_ = "";
+ const string xla_cluster_ = "";
const std::unordered_set colocation_constraints_;
// If true, Scope::DoShapeInference() always returns Status:OK().
diff --git a/tensorflow/cc/gradients/nn_grad.cc b/tensorflow/cc/gradients/nn_grad.cc
index 588e96cb196189780037f66266484962ba0385e4..2a32a2ed6f7862a29f4ce3d1aba5fdbc86adc670 100644
--- a/tensorflow/cc/gradients/nn_grad.cc
+++ b/tensorflow/cc/gradients/nn_grad.cc
@@ -143,6 +143,33 @@ Status Relu6GradHelper(const Scope& scope, const Operation& op,
}
REGISTER_GRADIENT_OP("Relu6", Relu6GradHelper);
+Status LeakyReluGradHelper(const Scope& scope, const Operation& op,
+ const std::vector