diff --git a/.github/ISSUE_TEMPLATE/bug-performance-issue.md b/.github/ISSUE_TEMPLATE/bug-performance-issue.md
new file mode 100644
index 0000000000000000000000000000000000000000..c590a962cb7b7cb4760be953a8d64fd96a0381a9
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug-performance-issue.md
@@ -0,0 +1,35 @@
+--------------------------------------------------------------------------------
+
+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/build-installation-issue.md b/.github/ISSUE_TEMPLATE/build-installation-issue.md
new file mode 100644
index 0000000000000000000000000000000000000000..fac9ddfbd70611f6448142d25cde6935a8e63b4f
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/build-installation-issue.md
@@ -0,0 +1,27 @@
+--------------------------------------------------------------------------------
+
+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/documentation-issue.md b/.github/ISSUE_TEMPLATE/documentation-issue.md
new file mode 100644
index 0000000000000000000000000000000000000000..610da5dd467b7bc80d4eab20310e15ad6fbcf13b
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/documentation-issue.md
@@ -0,0 +1,18 @@
+--------------------------------------------------------------------------------
+
+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 to
+fix the doc Issue?**
diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md
new file mode 100644
index 0000000000000000000000000000000000000000..9f06e1759ff5ff57a72408fd5a74e20b5e7e6ef0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature-request.md
@@ -0,0 +1,21 @@
+--------------------------------------------------------------------------------
+
+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/other-issues.md b/.github/ISSUE_TEMPLATE/other-issues.md
new file mode 100644
index 0000000000000000000000000000000000000000..b53bdb3c1689398ef7624ae858dba61b0f5e0a54
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/other-issues.md
@@ -0,0 +1,21 @@
+--------------------------------------------------------------------------------
+
+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/CODEOWNERS b/CODEOWNERS
index 78f80c8d718983f00fd5010c3fe5d561124d3714..94cc865479cd6ab5cdb589490d3a2d650f06b160 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -2,6 +2,7 @@
/tenosrflow/core/debug @caisq
/tensorflow/core/platform/windows/ @mrry
+/tensorflow/core/platform/s3 @yongtang
/tensorflow/go @asimshankar
/tensorflow/java/ @asimshankar
/tensorflow/python/debug @caisq
@@ -30,14 +31,16 @@
/tensorflow/contrib/gan/ @joel-shor
/tensorflow/contrib/graph_editor/ @purpledog
# NEED OWNER: /tensorflow/contrib/grid_rnn/
+/tensorflow/contrib/hadoop @yongtang
/tensorflow/contrib/hvx/ @satok16
/tensorflow/contrib/integrate/ @shoyer
+/tensorflow/contrib/kafka @yongtang
/tensorflow/contrib/kernel_methods/ @petrosmol
+/tensorflow/contrib/kinesis @yongtang
/tensorflow/contrib/ios_examples/ @petewarden
/tensorflow/contrib/labeled_tensor/ @shoyer
/tensorflow/contrib/layers/ @fchollet @martinwicke
/tensorflow/contrib/learn/ @martinwicke @ispirmustafa @alextp
-/tensorflow/contrib/linalg/ @langmore
/tensorflow/contrib/linear_optimizer/ @petrosmol @andreasst @katsiapis
/tensorflow/contrib/lookup/ @ysuematsu @andreasst
/tensorflow/contrib/losses/ @alextp @ispirmustafa
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 5fff9d05a1c589636bc9c711e6eb7cc4aba86b2f..20601eaf611d98f78382a7d260629e72e24a07c0 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.
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 e3092e551e32d7f01e9bebd65323d1b5691f0269..0c8d4d4ef08ec2598bf55ec1f168323f6ad755e1 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/get_started/os_setup.html) 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:
@@ -48,15 +62,12 @@ $ python
```
```python
>>> import tensorflow as tf
+>>> tf.enable_eager_execution()
+>>> tf.add(1, 2)
+3
>>> hello = tf.constant('Hello, TensorFlow!')
->>> sess = tf.Session()
->>> sess.run(hello)
+>>> hello.numpy()
'Hello, TensorFlow!'
->>> a = tf.constant(10)
->>> b = tf.constant(32)
->>> sess.run(a + b)
-42
->>> sess.close()
```
Learn more examples about how to do specific tasks in TensorFlow at the [tutorials page of tensorflow.org](https://www.tensorflow.org/tutorials/).
@@ -68,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:
@@ -96,23 +108,23 @@ 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.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)
## For more information
+* [TensorFlow Website](https://www.tensorflow.org)
+* [TensorFlow Tutorials](https://www.tensorflow.org/tutorials/)
+* [TensorFlow Model Zoo](https://github.com/tensorflow/models)
+* [TensorFlow Twitter](https://twitter.com/tensorflow)
* [TensorFlow Blog](https://medium.com/tensorflow)
* [TensorFlow Course at Stanford](https://web.stanford.edu/class/cs20si)
-* [TensorFlow Model Zoo](https://github.com/tensorflow/models)
-* [TensorFlow MOOC on Udacity](https://www.udacity.com/course/deep-learning--ud730)
* [TensorFlow Roadmap](https://www.tensorflow.org/community/roadmap)
-* [TensorFlow Twitter](https://twitter.com/tensorflow)
-* [TensorFlow Website](https://www.tensorflow.org)
* [TensorFlow White Papers](https://www.tensorflow.org/about/bib)
* [TensorFlow YouTube Channel](https://www.youtube.com/channel/UC0rqucBdTuFTjJiefW5t-IQ)
diff --git a/RELEASE.md b/RELEASE.md
index 763ef3b279dde209ed387534032deae40a33a9e4..2b00d06580d925a4afed5753afb8f51f0ebac99f 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -1,3 +1,190 @@
+# 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
+
+* Nvidia GPU:
+ * Prebuilt binaries are now (as of TensorFlow 1.11) built against cuDNN 7.2 and TensorRT 4. See updated install guides: [Installing TensorFlow on Ubuntu](https://www.tensorflow.org/install/install_linux#tensorflow_gpu_support)
+* Google Cloud TPU:
+ * Experimental tf.data integration for Keras on Google Cloud TPUs.
+ * Experimental / preview support for eager execution on Google Cloud TPUs.
+* DistributionStrategy:
+ * Add multi-GPU DistributionStrategy support in tf.keras. Users can now use `fit`, `evaluate` and `predict` to distribute their model on multiple GPUs.
+ * Add multi-worker DistributionStrategy and standalone client support in Estimator. See [README] (https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/distribute) for more details.
+* Add C, C++, and Python functions for querying kernels
+
+## Breaking Changes
+
+* Keras:
+ * The default values for tf.keras `RandomUniform`, `RandomNormal`, and `TruncatedNormal` initializers have been changed to match those in external Keras.
+ * Breaking change: `model.get_config()` on a Sequential model now returns a config dictionary (consistent with other Model instances) instead of a list of configs for the underlying layers.
+
+## 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
+ * 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
+
+This release contains contributions from many people at Google, as well as:
+
+Aapeli, adoda, Ag Ramesh, Amogh Mannekote, Andrew Gibiansky, Andy Craze, Anirudh Koul, Aurelien Geron, Avijit, Avijit-Nervana, Ben, Benjamin H. Myara, bhack, Brett Koonce, Cao Zongyan, cbockman, cheerss, Chikanaga Tomoyuki, Clayne Robison, cosine0, Cui Wei, Dan J, David, David Norman, Dmitry Klimenkov, Eliel Hojman, Florian Courtial, fo40225, formath, Geoffrey Irving, gracehoney, Grzegorz Pawelczak, Guoliang Hua, Guozhong Zhuang, Herman Zvonimir DošIlović, HuiyangFei, Jacker, Jan HüNnemeyer, Jason Taylor, Jason Zaman, Jesse, Jiang,Zhoulong, Jiawei Zhang, Jie, Joe Yearsley, Johannes Schmitz, Jon Perl, Jon Triebenbach, Jonathan, Jonathan Hseu, Jongmin Park, Justin Shenk, karl@kubx.ca, Kate Hodesdon, Kb Sriram, Keishi Hattori, Kenneth Blomqvist, Koan-Sin Tan, Li Liangbin, Li, Yiqiang, Loo Rong Jie, Madiyar, Mahmoud Abuzaina, Mark Ryan, Matt Dodge, mbhuiyan, melvinljy96, Miguel Mota, Nafis Sadat, Nathan Luehr, naurril, Nehal J Wani, Niall Moran, Niranjan Hasabnis, Nishidha Panpaliya, npow, olicht, Pei Zhang, Peng Wang (Simpeng), Peng Yu, Philipp Jund, Pradeep Banavara, Pratik Kalshetti, qwertWZ, Rakesh Chada, Randy West, Ray Kim, Rholais Lii, Robin Richtsfeld, Rodrigo Silveira, Ruizhi, Santosh Kumar, Seb Bro, Sergei Lebedev, sfujiwara, Shaba Abhiram, Shashi, SneakyFish5, Soila Kavulya, Stefan Dyulgerov, Steven Winston, Sunitha Kambhampati, Surry Shome, Taehoon Lee, Thor Johnsen, Tristan Rice, TShapinsky, tucan, tucan9389, Vicente Reyes, Vilmar-Hillow, Vitaly Lavrukhin, wangershi, weidan.kong, weidankong, Wen-Heng (Jack) Chung, William D. Irons, Wim Glenn, XFeiF, Yan Facai (颜发才), Yanbo Liang, Yong Tang, Yoshihiro Yamazaki, Yuan (Terry) Tang, Yuan, Man, zhaoyongke, ÁRon
+Ricardo Perez-Lopez, 张天启, 张晓飞
+
+
+# Release 1.10.1
+## Bug Fixes and Other Changes
+
+* `tf.keras`:
+ * Fixing keras on Cloud TPUs. No new binaries will be built for Windows.
+
+
# Release 1.10.0
## Major Features And Improvements
@@ -11,7 +198,7 @@
## Breaking Changes
-* Prebuilt binaries are now (as of TensorFlow 1.10) built against NCCL 2.2 and no longer include NCCL in the binary install. TensorFlow usage with multiple GPUs and NCCL requires upgrade to [NCCL 2.2](https://developer.nvidia.com/nccl). See updated install guides: [Installing TensorFlow on Ubuntu](https://www.tensorflow.org/install/install_linux#tensorflow_gpu_support) and [Install TensorFlow from Sources](https://www.tensorflow.org/install/install_sources#optional_install_tensorflow_for_gpu_prerequisites).
+* Prebuilt binaries are now (as of TensorFlow 1.10) built against NCCL 2.2 and no longer include NCCL in the binary install. TensorFlow usage with multiple GPUs and NCCL requires upgrade to [NCCL 2.2](https://developer.nvidia.com/nccl). See updated install guides: [TensorFlow GPU support](https://www.tensorflow.org/install/gpu) and [Build TensorFlow from source](https://www.tensorflow.org/install/source).
* Starting from TensorFlow 1.11, Windows builds will use Bazel. Therefore, we will drop official support for cmake.
## Bug Fixes and Other Changes
diff --git a/configure.py b/configure.py
index 361bd4764dc5c1900be7378f51c00aedf6f2ce41..b564da27227ec07713f91e925ea292b35f0f02df 100644
--- a/configure.py
+++ b/configure.py
@@ -35,13 +35,11 @@ except ImportError:
_DEFAULT_CUDA_VERSION = '9.0'
_DEFAULT_CUDNN_VERSION = '7'
-_DEFAULT_NCCL_VERSION = '2.2'
_DEFAULT_CUDA_COMPUTE_CAPABILITIES = '3.5,7.0'
_DEFAULT_CUDA_PATH = '/usr/local/cuda'
_DEFAULT_CUDA_PATH_LINUX = '/opt/cuda'
_DEFAULT_CUDA_PATH_WIN = ('C:/Program Files/NVIDIA GPU Computing '
'Toolkit/CUDA/v%s' % _DEFAULT_CUDA_VERSION)
-_DEFAULT_TENSORRT_PATH_LINUX = '/usr/lib/%s-linux-gnu' % platform.machine()
_TF_OPENCL_VERSION = '1.2'
_DEFAULT_COMPUTECPP_TOOLKIT_PATH = '/usr/local/computecpp'
_DEFAULT_TRISYCL_INCLUDE_DIR = '/usr/local/triSYCL/include'
@@ -49,10 +47,18 @@ _SUPPORTED_ANDROID_NDK_VERSIONS = [10, 11, 12, 13, 14, 15, 16]
_DEFAULT_PROMPT_ASK_ATTEMPTS = 10
-_TF_WORKSPACE_ROOT = os.path.abspath(os.path.dirname(__file__))
_TF_BAZELRC_FILENAME = '.tf_configure.bazelrc'
-_TF_BAZELRC = os.path.join(_TF_WORKSPACE_ROOT, _TF_BAZELRC_FILENAME)
-_TF_WORKSPACE = os.path.join(_TF_WORKSPACE_ROOT, 'WORKSPACE')
+_TF_WORKSPACE_ROOT = ''
+_TF_BAZELRC = ''
+
+NCCL_LIB_PATHS = [
+ 'lib64/', 'lib/powerpc64le-linux-gnu/', 'lib/x86_64-linux-gnu/', ''
+]
+
+if platform.machine() == 'ppc64le':
+ _DEFAULT_TENSORRT_PATH_LINUX = '/usr/lib/powerpc64le-linux-gnu/'
+else:
+ _DEFAULT_TENSORRT_PATH_LINUX = '/usr/lib/%s-linux-gnu' % platform.machine()
class UserInputError(Exception):
@@ -153,14 +159,18 @@ def get_python_path(environ_cp, python_bin_path):
if environ_cp.get('PYTHONPATH'):
python_paths = environ_cp.get('PYTHONPATH').split(':')
try:
- library_paths = run_shell(
- [python_bin_path, '-c',
- 'import site; print("\\n".join(site.getsitepackages()))']).split('\n')
+ library_paths = run_shell([
+ python_bin_path, '-c',
+ 'import site; print("\\n".join(site.getsitepackages()))'
+ ]).split('\n')
except subprocess.CalledProcessError:
- library_paths = [run_shell(
- [python_bin_path, '-c',
- 'from distutils.sysconfig import get_python_lib;'
- 'print(get_python_lib())'])]
+ library_paths = [
+ run_shell([
+ python_bin_path, '-c',
+ 'from distutils.sysconfig import get_python_lib;'
+ 'print(get_python_lib())'
+ ])
+ ]
all_paths = set(python_paths + library_paths)
@@ -187,8 +197,7 @@ def setup_python(environ_cp):
environ_cp, 'PYTHON_BIN_PATH', ask_python_bin_path,
default_python_bin_path)
# Check if the path is valid
- if os.path.isfile(python_bin_path) and os.access(
- python_bin_path, os.X_OK):
+ if os.path.isfile(python_bin_path) and os.access(python_bin_path, os.X_OK):
break
elif not os.path.exists(python_bin_path):
print('Invalid python path: %s cannot be found.' % python_bin_path)
@@ -217,7 +226,7 @@ def setup_python(environ_cp):
python_lib_path = default_python_lib_path
environ_cp['PYTHON_LIB_PATH'] = python_lib_path
- python_major_version = get_python_major_version(python_bin_path)
+ _ = get_python_major_version(python_bin_path)
# Convert python path to Windows style before writing into bazel.rc
if is_windows() or is_cygwin():
@@ -230,15 +239,16 @@ def setup_python(environ_cp):
environ_cp['PYTHON_BIN_PATH'] = python_bin_path
# Write tools/python_bin_path.sh
- with open(os.path.join(
- _TF_WORKSPACE_ROOT, 'tools', 'python_bin_path.sh'), 'w') as f:
+ with open(
+ os.path.join(_TF_WORKSPACE_ROOT, 'tools', 'python_bin_path.sh'),
+ 'w') as f:
f.write('export PYTHON_BIN_PATH="%s"' % python_bin_path)
-def reset_tf_configure_bazelrc(workspace_path):
+def reset_tf_configure_bazelrc():
"""Reset file that contains customized config settings."""
open(_TF_BAZELRC, 'w').close()
- bazelrc_path = os.path.join(workspace_path, '.bazelrc')
+ bazelrc_path = os.path.join(_TF_WORKSPACE_ROOT, '.bazelrc')
data = []
if os.path.exists(bazelrc_path):
@@ -249,20 +259,15 @@ def reset_tf_configure_bazelrc(workspace_path):
if _TF_BAZELRC_FILENAME in l:
continue
f.write('%s\n' % l)
- if is_windows():
- tf_bazelrc_path = _TF_BAZELRC.replace("\\", "/")
- else:
- tf_bazelrc_path = _TF_BAZELRC
- f.write('import %s\n' % tf_bazelrc_path)
-
+ f.write('import %%workspace%%/%s\n' % _TF_BAZELRC_FILENAME)
def cleanup_makefile():
"""Delete any leftover BUILD files from the Makefile build.
These files could interfere with Bazel parsing.
"""
- makefile_download_dir = os.path.join(
- _TF_WORKSPACE_ROOT, 'tensorflow', 'contrib', 'makefile', 'downloads')
+ makefile_download_dir = os.path.join(_TF_WORKSPACE_ROOT, 'tensorflow',
+ 'contrib', 'makefile', 'downloads')
if os.path.isdir(makefile_download_dir):
for root, _, filenames in os.walk(makefile_download_dir):
for f in filenames:
@@ -330,9 +335,8 @@ def get_var(environ_cp,
'Environment variable %s must be set as a boolean indicator.\n'
'The following are accepted as TRUE : %s.\n'
'The following are accepted as FALSE: %s.\n'
- 'Current value is %s.' % (
- var_name, ', '.join(true_strings), ', '.join(false_strings),
- var))
+ 'Current value is %s.' % (var_name, ', '.join(true_strings),
+ ', '.join(false_strings), var))
while var is None:
user_input_origin = get_input(question)
@@ -355,8 +359,12 @@ def get_var(environ_cp,
return var
-def set_build_var(environ_cp, var_name, query_item, option_name,
- enabled_by_default, bazel_config_name=None):
+def set_build_var(environ_cp,
+ var_name,
+ query_item,
+ option_name,
+ enabled_by_default,
+ bazel_config_name=None):
"""Set if query_item will be enabled for the build.
Ask user if query_item will be enabled. Default is used if no input is given.
@@ -375,12 +383,14 @@ def set_build_var(environ_cp, var_name, query_item, option_name,
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.
- write_to_bazelrc('build:%s --define %s=true'
- % (bazel_config_name, option_name))
+ write_to_bazelrc(
+ 'build:%s --define %s=true' % (bazel_config_name, option_name))
def set_action_env_var(environ_cp,
@@ -447,7 +457,8 @@ def check_bazel_version(min_version):
if which('bazel') is None:
print('Cannot find bazel. Please install bazel.')
sys.exit(0)
- curr_version = run_shell(['bazel', '--batch', '--bazelrc=/dev/null', 'version'])
+ curr_version = run_shell(
+ ['bazel', '--batch', '--bazelrc=/dev/null', 'version'])
for line in curr_version.split('\n'):
if 'Build label: ' in line:
@@ -486,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
@@ -499,6 +510,7 @@ def set_cc_opt_flags(environ_cp):
write_to_bazelrc('build:opt --host_copt=-march=native')
write_to_bazelrc('build:opt --define with_default_optimizations=true')
+
def set_tf_cuda_clang(environ_cp):
"""set TF_CUDA_CLANG action_env.
@@ -581,16 +593,14 @@ def set_clang_cuda_compiler_path(environ_cp):
clang_cuda_compiler_path)
-def prompt_loop_or_load_from_env(
- environ_cp,
- var_name,
- var_default,
- ask_for_var,
- check_success,
- error_msg,
- suppress_default_error=False,
- n_ask_attempts=_DEFAULT_PROMPT_ASK_ATTEMPTS
-):
+def prompt_loop_or_load_from_env(environ_cp,
+ var_name,
+ var_default,
+ ask_for_var,
+ check_success,
+ error_msg,
+ suppress_default_error=False,
+ n_ask_attempts=_DEFAULT_PROMPT_ASK_ATTEMPTS):
"""Loop over user prompts for an ENV param until receiving a valid response.
For the env param var_name, read from the environment or verify user input
@@ -629,9 +639,7 @@ def prompt_loop_or_load_from_env(
)
for _ in range(n_ask_attempts):
- val = get_from_env_or_user_or_default(environ_cp,
- var_name,
- full_query,
+ val = get_from_env_or_user_or_default(environ_cp, var_name, full_query,
default)
if check_success(val):
break
@@ -639,9 +647,9 @@ def prompt_loop_or_load_from_env(
print(error_msg % val)
environ_cp[var_name] = ''
else:
- raise UserInputError('Invalid %s setting was provided %d times in a row. '
- 'Assuming to be a scripting mistake.' %
- (var_name, n_ask_attempts))
+ raise UserInputError(
+ 'Invalid %s setting was provided %d times in a row. '
+ 'Assuming to be a scripting mistake.' % (var_name, n_ask_attempts))
environ_cp[var_name] = val
return val
@@ -650,8 +658,8 @@ def prompt_loop_or_load_from_env(
def create_android_ndk_rule(environ_cp):
"""Set ANDROID_NDK_HOME and write Android NDK WORKSPACE rule."""
if is_windows() or is_cygwin():
- default_ndk_path = cygpath('%s/Android/Sdk/ndk-bundle' %
- environ_cp['APPDATA'])
+ default_ndk_path = cygpath(
+ '%s/Android/Sdk/ndk-bundle' % environ_cp['APPDATA'])
elif is_macos():
default_ndk_path = '%s/library/Android/Sdk/ndk-bundle' % environ_cp['HOME']
else:
@@ -668,8 +676,7 @@ def create_android_ndk_rule(environ_cp):
ask_for_var='Please specify the home path of the Android NDK to use.',
check_success=valid_ndk_path,
error_msg=('The path %s or its child file "source.properties" '
- 'does not exist.')
- )
+ 'does not exist.'))
write_action_env_to_bazelrc('ANDROID_NDK_HOME', android_ndk_home_path)
write_action_env_to_bazelrc('ANDROID_NDK_API_LEVEL',
check_ndk_level(android_ndk_home_path))
@@ -703,9 +710,9 @@ def create_android_sdk_rule(environ_cp):
api_levels = [x.replace('android-', '') for x in api_levels]
def valid_api_level(api_level):
- return os.path.exists(os.path.join(android_sdk_home_path,
- 'platforms',
- 'android-' + api_level))
+ return os.path.exists(
+ os.path.join(android_sdk_home_path, 'platforms',
+ 'android-' + api_level))
android_api_level = prompt_loop_or_load_from_env(
environ_cp,
@@ -720,9 +727,8 @@ def create_android_sdk_rule(environ_cp):
versions = sorted(os.listdir(build_tools))
def valid_build_tools(version):
- return os.path.exists(os.path.join(android_sdk_home_path,
- 'build-tools',
- version))
+ return os.path.exists(
+ os.path.join(android_sdk_home_path, 'build-tools', version))
android_build_tools_version = prompt_loop_or_load_from_env(
environ_cp,
@@ -736,10 +742,8 @@ def create_android_sdk_rule(environ_cp):
write_action_env_to_bazelrc('ANDROID_BUILD_TOOLS_VERSION',
android_build_tools_version)
- write_action_env_to_bazelrc('ANDROID_SDK_API_LEVEL',
- android_api_level)
- write_action_env_to_bazelrc('ANDROID_SDK_HOME',
- android_sdk_home_path)
+ write_action_env_to_bazelrc('ANDROID_SDK_API_LEVEL', android_api_level)
+ write_action_env_to_bazelrc('ANDROID_SDK_HOME', android_sdk_home_path)
def check_ndk_level(android_ndk_home_path):
@@ -798,6 +802,7 @@ def reformat_version_sequence(version_str, sequence_count):
Args:
version_str: String, the version string.
sequence_count: int, an integer.
+
Returns:
string, reformatted version string.
"""
@@ -841,18 +846,25 @@ def set_tf_cuda_version(environ_cp):
if is_windows():
cuda_rt_lib_paths = ['lib/x64/cudart.lib']
elif is_linux():
- cuda_rt_lib_paths = ['%s/libcudart.so.%s' % (x, tf_cuda_version)
- for x in ['lib64', 'lib/x86_64-linux-gnu']]
+ cuda_rt_lib_paths = [
+ '%s/libcudart.so.%s' % (x, tf_cuda_version) for x in [
+ 'lib64',
+ 'lib/powerpc64le-linux-gnu',
+ 'lib/x86_64-linux-gnu',
+ ]
+ ]
elif is_macos():
cuda_rt_lib_paths = ['lib/libcudart.%s.dylib' % tf_cuda_version]
- cuda_toolkit_paths_full = [os.path.join(cuda_toolkit_path, x) for x in cuda_rt_lib_paths]
+ cuda_toolkit_paths_full = [
+ os.path.join(cuda_toolkit_path, x) for x in cuda_rt_lib_paths
+ ]
if any([os.path.exists(x) for x in cuda_toolkit_paths_full]):
break
# Reset and retry
print('Invalid path to CUDA %s toolkit. %s cannot be found' %
- (tf_cuda_version, cuda_toolkit_path_full))
+ (tf_cuda_version, cuda_toolkit_paths_full))
environ_cp['TF_CUDA_VERSION'] = ''
environ_cp['CUDA_TOOLKIT_PATH'] = ''
@@ -872,7 +884,7 @@ def set_tf_cudnn_version(environ_cp):
"""Set CUDNN_INSTALL_PATH and TF_CUDNN_VERSION."""
ask_cudnn_version = (
'Please specify the cuDNN version you want to use. '
- '[Leave empty to default to cuDNN %s.0]: ') % _DEFAULT_CUDNN_VERSION
+ '[Leave empty to default to cuDNN %s]: ') % _DEFAULT_CUDNN_VERSION
for _ in range(_DEFAULT_PROMPT_ASK_ATTEMPTS):
tf_cudnn_version = get_from_env_or_user_or_default(
@@ -919,8 +931,8 @@ def set_tf_cudnn_version(environ_cp):
cudnn_path_from_ldconfig)
if cudnn_path_from_ldconfig:
cudnn_path_from_ldconfig = cudnn_path_from_ldconfig.group(1)
- if os.path.exists('%s.%s' % (cudnn_path_from_ldconfig,
- tf_cudnn_version)):
+ if os.path.exists(
+ '%s.%s' % (cudnn_path_from_ldconfig, tf_cudnn_version)):
cudnn_install_path = os.path.dirname(cudnn_path_from_ldconfig)
break
@@ -1029,7 +1041,7 @@ def set_tf_tensorrt_install_path(environ_cp):
for lib_file in possible_files:
if is_cuda_compatible(lib_file, cuda_ver, cudnn_ver):
matches = nvinfer_pattern.search(lib_file)
- if len(matches.groups()) == 0:
+ if not matches.groups():
continue
ver_str = matches.group(1)
ver = convert_version_to_int(ver_str) if len(ver_str) else 0
@@ -1085,7 +1097,7 @@ def set_tf_tensorrt_install_path(environ_cp):
def set_tf_nccl_install_path(environ_cp):
- """Set NCCL_INSTALL_PATH and TF_NCCL_VERSION.
+ """Set NCCL_INSTALL_PATH, NCCL_HDR_PATH and TF_NCCL_VERSION.
Args:
environ_cp: copy of the os.environ.
@@ -1098,59 +1110,119 @@ def set_tf_nccl_install_path(environ_cp):
raise ValueError('Currently NCCL is only supported on Linux platforms.')
ask_nccl_version = (
- 'Please specify the NCCL version you want to use. If NCCL %s is not '
- 'installed, then you can use version 1.3 that can be fetched '
- 'automatically but it may have worse performance with multiple GPUs. '
- '[Default is %s]: ') % (_DEFAULT_NCCL_VERSION, _DEFAULT_NCCL_VERSION)
+ 'Please specify the locally installed NCCL version you want to use. '
+ '[Default is to use https://github.com/nvidia/nccl]: ')
for _ in range(_DEFAULT_PROMPT_ASK_ATTEMPTS):
tf_nccl_version = get_from_env_or_user_or_default(
- environ_cp, 'TF_NCCL_VERSION', ask_nccl_version, _DEFAULT_NCCL_VERSION)
- tf_nccl_version = reformat_version_sequence(str(tf_nccl_version), 1)
+ environ_cp, 'TF_NCCL_VERSION', ask_nccl_version, '')
+
+ if not tf_nccl_version:
+ break # No need to get install path, building the open source code.
- if tf_nccl_version == '1':
- break # No need to get install path, NCCL 1 is a GitHub repo.
+ tf_nccl_version = reformat_version_sequence(str(tf_nccl_version), 1)
- # TODO(csigg): Look with ldconfig first if we can find the library in paths
+ # Look with ldconfig first if we can find the library in paths
# like /usr/lib/x86_64-linux-gnu and the header file in the corresponding
# include directory. This is where the NCCL .deb packages install them.
- # Then ask the user if we should use that. Instead of a single
- # NCCL_INSTALL_PATH, pass separate NCCL_LIB_PATH and NCCL_HDR_PATH to
- # nccl_configure.bzl
- default_nccl_path = environ_cp.get('CUDA_TOOLKIT_PATH')
- ask_nccl_path = (r'Please specify the location where NCCL %s library is '
- 'installed. Refer to README.md for more details. [Default '
- 'is %s]:') % (tf_nccl_version, default_nccl_path)
- nccl_install_path = get_from_env_or_user_or_default(
- environ_cp, 'NCCL_INSTALL_PATH', ask_nccl_path, default_nccl_path)
- # Result returned from "read" will be used unexpanded. That make "~"
- # unusable. Going through one more level of expansion to handle that.
- nccl_install_path = os.path.realpath(os.path.expanduser(nccl_install_path))
- if is_windows() or is_cygwin():
- nccl_install_path = cygpath(nccl_install_path)
-
- if is_windows():
- nccl_lib_path = 'lib/x64/nccl.lib'
- elif is_linux():
- nccl_lib_path = 'lib/libnccl.so.%s' % tf_nccl_version
- elif is_macos():
- nccl_lib_path = 'lib/libnccl.%s.dylib' % tf_nccl_version
-
- nccl_lib_path = os.path.join(nccl_install_path, nccl_lib_path)
- nccl_hdr_path = os.path.join(nccl_install_path, 'include/nccl.h')
- if os.path.exists(nccl_lib_path) and os.path.exists(nccl_hdr_path):
- # Set NCCL_INSTALL_PATH
- environ_cp['NCCL_INSTALL_PATH'] = nccl_install_path
- write_action_env_to_bazelrc('NCCL_INSTALL_PATH', nccl_install_path)
- break
-
- # Reset and Retry
- print('Invalid path to NCCL %s toolkit, %s or %s not found. Please use the '
+ # First check to see if NCCL is in the ldconfig.
+ # If its found, use that location.
+ if is_linux():
+ ldconfig_bin = which('ldconfig') or '/sbin/ldconfig'
+ nccl2_path_from_ldconfig = run_shell([ldconfig_bin, '-p'])
+ nccl2_path_from_ldconfig = re.search('.*libnccl.so .* => (.*)',
+ nccl2_path_from_ldconfig)
+ if nccl2_path_from_ldconfig:
+ nccl2_path_from_ldconfig = nccl2_path_from_ldconfig.group(1)
+ if os.path.exists('%s.%s' % (nccl2_path_from_ldconfig, tf_nccl_version)):
+ nccl_install_path = os.path.dirname(nccl2_path_from_ldconfig)
+ print('NCCL libraries found in ' + nccl2_path_from_ldconfig)
+
+ # Check if this is the main system lib location
+ if re.search('.*linux-gnu', nccl_install_path):
+ trunc_nccl_install_path = '/usr'
+ print('This looks like a system path.')
+ else:
+ trunc_nccl_install_path = nccl_install_path + '/..'
+
+ # Look for header
+ nccl_hdr_path = trunc_nccl_install_path + '/include'
+ print('Assuming NCCL header path is ' + nccl_hdr_path)
+ if os.path.exists(nccl_hdr_path + '/nccl.h'):
+ # Set NCCL_INSTALL_PATH
+ environ_cp['NCCL_INSTALL_PATH'] = nccl_install_path
+ write_action_env_to_bazelrc('NCCL_INSTALL_PATH', nccl_install_path)
+
+ # Set NCCL_HDR_PATH
+ environ_cp['NCCL_HDR_PATH'] = nccl_hdr_path
+ write_action_env_to_bazelrc('NCCL_HDR_PATH', nccl_hdr_path)
+ break
+ else:
+ print(
+ 'The header for NCCL2 cannot be found. Please install the libnccl-dev package.'
+ )
+ else:
+ print('NCCL2 is listed by ldconfig but the library is not found. '
+ 'Your ldconfig is out of date. Please run sudo ldconfig.')
+ else:
+ # NCCL is not found in ldconfig. Ask the user for the location.
+ default_nccl_path = environ_cp.get('CUDA_TOOLKIT_PATH')
+ ask_nccl_path = (
+ r'Please specify the location where NCCL %s library is '
+ 'installed. Refer to README.md for more details. [Default '
+ 'is %s]:') % (tf_nccl_version, default_nccl_path)
+ nccl_install_path = get_from_env_or_user_or_default(
+ environ_cp, 'NCCL_INSTALL_PATH', ask_nccl_path, default_nccl_path)
+
+ # Result returned from "read" will be used unexpanded. That make "~"
+ # unusable. Going through one more level of expansion to handle that.
+ nccl_install_path = os.path.realpath(
+ os.path.expanduser(nccl_install_path))
+ if is_windows() or is_cygwin():
+ nccl_install_path = cygpath(nccl_install_path)
+
+ if is_windows():
+ nccl_lib_path = 'lib/x64/nccl.lib'
+ elif is_linux():
+ nccl_lib_filename = 'libnccl.so.%s' % tf_nccl_version
+ nccl_lpath = '%s/lib/%s' % (nccl_install_path, nccl_lib_filename)
+ if not os.path.exists(nccl_lpath):
+ for relative_path in NCCL_LIB_PATHS:
+ path = '%s/%s%s' % (nccl_install_path, relative_path,
+ nccl_lib_filename)
+ if os.path.exists(path):
+ print('NCCL found at ' + path)
+ nccl_lib_path = path
+ break
+ else:
+ nccl_lib_path = nccl_lpath
+ elif is_macos():
+ nccl_lib_path = 'lib/libnccl.%s.dylib' % tf_nccl_version
+
+ nccl_lib_path = os.path.join(nccl_install_path, nccl_lib_path)
+ nccl_hdr_path = os.path.join(
+ os.path.dirname(nccl_lib_path), '../include/nccl.h')
+ print('Assuming NCCL header path is ' + nccl_hdr_path)
+ if os.path.exists(nccl_lib_path) and os.path.exists(nccl_hdr_path):
+ # Set NCCL_INSTALL_PATH
+ environ_cp['NCCL_INSTALL_PATH'] = os.path.dirname(nccl_lib_path)
+ write_action_env_to_bazelrc('NCCL_INSTALL_PATH',
+ os.path.dirname(nccl_lib_path))
+
+ # Set NCCL_HDR_PATH
+ environ_cp['NCCL_HDR_PATH'] = os.path.dirname(nccl_hdr_path)
+ write_action_env_to_bazelrc('NCCL_HDR_PATH',
+ os.path.dirname(nccl_hdr_path))
+ break
+
+ # Reset and Retry
+ print(
+ 'Invalid path to NCCL %s toolkit, %s or %s not found. Please use the '
'O/S agnostic package of NCCL 2' % (tf_nccl_version, nccl_lib_path,
nccl_hdr_path))
- environ_cp['TF_NCCL_VERSION'] = ''
+ environ_cp['TF_NCCL_VERSION'] = ''
else:
raise UserInputError('Invalid TF_NCCL setting was provided %d '
'times in a row. Assuming to be a scripting mistake.' %
@@ -1160,12 +1232,12 @@ def set_tf_nccl_install_path(environ_cp):
environ_cp['TF_NCCL_VERSION'] = tf_nccl_version
write_action_env_to_bazelrc('TF_NCCL_VERSION', tf_nccl_version)
-
def get_native_cuda_compute_capabilities(environ_cp):
"""Get native cuda compute capabilities.
Args:
environ_cp: copy of the os.environ.
+
Returns:
string of native cuda compute capabilities, separated by comma.
"""
@@ -1290,8 +1362,7 @@ def set_computecpp_toolkit_path(environ_cp):
else:
sycl_rt_lib_path = ''
- sycl_rt_lib_path_full = os.path.join(toolkit_path,
- sycl_rt_lib_path)
+ sycl_rt_lib_path_full = os.path.join(toolkit_path, sycl_rt_lib_path)
exists = os.path.exists(sycl_rt_lib_path_full)
if not exists:
print('Invalid SYCL %s library path. %s cannot be found' %
@@ -1319,8 +1390,8 @@ def set_trisycl_include_dir(environ_cp):
ask_trisycl_include_dir = ('Please specify the location of the triSYCL '
'include directory. (Use --config=sycl_trisycl '
'when building with Bazel) '
- '[Default is %s]: '
- ) % (_DEFAULT_TRISYCL_INCLUDE_DIR)
+ '[Default is %s]: ') % (
+ _DEFAULT_TRISYCL_INCLUDE_DIR)
while True:
trisycl_include_dir = get_from_env_or_user_or_default(
@@ -1329,13 +1400,12 @@ def set_trisycl_include_dir(environ_cp):
if os.path.exists(trisycl_include_dir):
break
- print('Invalid triSYCL include directory, %s cannot be found'
- % (trisycl_include_dir))
+ print('Invalid triSYCL include directory, %s cannot be found' %
+ (trisycl_include_dir))
# Set TRISYCL_INCLUDE_DIR
environ_cp['TRISYCL_INCLUDE_DIR'] = trisycl_include_dir
- write_action_env_to_bazelrc('TRISYCL_INCLUDE_DIR',
- trisycl_include_dir)
+ write_action_env_to_bazelrc('TRISYCL_INCLUDE_DIR', trisycl_include_dir)
def set_mpi_home(environ_cp):
@@ -1345,8 +1415,9 @@ def set_mpi_home(environ_cp):
default_mpi_home = os.path.dirname(os.path.dirname(default_mpi_home))
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')))
+ exists = (
+ os.path.exists(os.path.join(mpi_home, 'include')) and
+ os.path.exists(os.path.join(mpi_home, 'lib')))
if not exists:
print('Invalid path to the MPI Toolkit. %s or %s cannot be found' %
(os.path.join(mpi_home, 'include'),
@@ -1395,16 +1466,22 @@ def set_other_mpi_vars(environ_cp):
raise ValueError('Cannot find the MPI library file in %s/lib' % mpi_home)
-def set_grpc_build_flags():
- write_to_bazelrc('build --define grpc_no_ares=true')
-
-
def set_system_libs_flag(environ_cp):
syslibs = environ_cp.get('TF_SYSTEM_LIBS', '')
- syslibs = ','.join(sorted(syslibs.split(',')))
- if syslibs and syslibs != '':
+ if syslibs:
+ if ',' in syslibs:
+ syslibs = ','.join(sorted(syslibs.split(',')))
+ else:
+ syslibs = ','.join(sorted(syslibs.split()))
write_action_env_to_bazelrc('TF_SYSTEM_LIBS', syslibs)
+ if 'PREFIX' in environ_cp:
+ write_to_bazelrc('build --define=PREFIX=%s' % environ_cp['PREFIX'])
+ if 'LIBDIR' in environ_cp:
+ write_to_bazelrc('build --define=LIBDIR=%s' % environ_cp['LIBDIR'])
+ if 'INCLUDEDIR' in environ_cp:
+ write_to_bazelrc('build --define=INCLUDEDIR=%s' % environ_cp['INCLUDEDIR'])
+
def set_windows_build_flags(environ_cp):
"""Set Windows specific build options."""
@@ -1424,11 +1501,9 @@ def set_windows_build_flags(environ_cp):
if get_var(
environ_cp, 'TF_OVERRIDE_EIGEN_STRONG_INLINE', 'Eigen strong inline',
- True,
- ('Would you like to override eigen strong inline for some C++ '
- 'compilation to reduce the compilation time?'),
- 'Eigen strong inline overridden.',
- 'Not overriding eigen strong inline, '
+ True, ('Would you like to override eigen strong inline for some C++ '
+ 'compilation to reduce the compilation time?'),
+ 'Eigen strong inline overridden.', 'Not overriding eigen strong inline, '
'some compilations could take more than 20 mins.'):
# Due to a known MSVC compiler issue
# https://github.com/tensorflow/tensorflow/issues/10521
@@ -1444,29 +1519,31 @@ def config_info_line(name, help_text):
def main():
+ global _TF_WORKSPACE_ROOT
+ global _TF_BAZELRC
+
parser = argparse.ArgumentParser()
- parser.add_argument("--workspace",
- type=str,
- default=_TF_WORKSPACE_ROOT,
- help="The absolute path to your active Bazel workspace.")
+ parser.add_argument(
+ '--workspace',
+ type=str,
+ default=os.path.abspath(os.path.dirname(__file__)),
+ help='The absolute path to your active Bazel workspace.')
args = parser.parse_args()
+ _TF_WORKSPACE_ROOT = args.workspace
+ _TF_BAZELRC = os.path.join(_TF_WORKSPACE_ROOT, _TF_BAZELRC_FILENAME)
+
# Make a copy of os.environ to be clear when functions and getting and setting
# environment variables.
environ_cp = dict(os.environ)
check_bazel_version('0.15.0')
- reset_tf_configure_bazelrc(args.workspace)
+ reset_tf_configure_bazelrc()
cleanup_makefile()
setup_python(environ_cp)
if is_windows():
- environ_cp['TF_NEED_AWS'] = '0'
- environ_cp['TF_NEED_GCP'] = '0'
- environ_cp['TF_NEED_HDFS'] = '0'
- environ_cp['TF_NEED_JEMALLOC'] = '0'
- environ_cp['TF_NEED_KAFKA'] = '0'
environ_cp['TF_NEED_OPENCL_SYCL'] = '0'
environ_cp['TF_NEED_COMPUTECPP'] = '0'
environ_cp['TF_NEED_OPENCL'] = '0'
@@ -1475,14 +1552,10 @@ 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_GDR'] = '0'
- environ_cp['TF_NEED_VERBS'] = '0'
environ_cp['TF_NEED_MPI'] = '0'
environ_cp['TF_SET_ANDROID_WORKSPACE'] = '0'
if is_macos():
- environ_cp['TF_NEED_JEMALLOC'] = '0'
environ_cp['TF_NEED_TENSORRT'] = '0'
# The numpy package on ppc64le uses OpenBLAS which has multi-threading
@@ -1490,26 +1563,11 @@ def main():
# runtime to allow the Tensorflow testcases which compare numpy
# results to Tensorflow results to succeed.
if is_ppc64le():
- write_action_env_to_bazelrc("OMP_NUM_THREADS", 1)
-
- set_build_var(environ_cp, 'TF_NEED_JEMALLOC', 'jemalloc as malloc',
- 'with_jemalloc', True)
- set_build_var(environ_cp, 'TF_NEED_GCP', 'Google Cloud Platform',
- 'with_gcp_support', True, 'gcp')
- set_build_var(environ_cp, 'TF_NEED_HDFS', 'Hadoop File System',
- 'with_hdfs_support', True, 'hdfs')
- set_build_var(environ_cp, 'TF_NEED_AWS', 'Amazon AWS Platform',
- 'with_aws_support', True, 'aws')
- set_build_var(environ_cp, 'TF_NEED_KAFKA', 'Apache Kafka Platform',
- 'with_kafka_support', True, 'kafka')
+ write_action_env_to_bazelrc('OMP_NUM_THREADS', 1)
+
+ xla_enabled_by_default = is_linux()
set_build_var(environ_cp, 'TF_ENABLE_XLA', 'XLA JIT', 'with_xla_support',
- False, 'xla')
- set_build_var(environ_cp, 'TF_NEED_GDR', 'GDR', 'with_gdr_support',
- False, 'gdr')
- set_build_var(environ_cp, 'TF_NEED_VERBS', 'VERBS', 'with_verbs_support',
- False, 'verbs')
- set_build_var(environ_cp, 'TF_NEED_NGRAPH', 'nGraph',
- 'with_ngraph_support', False, 'ngraph')
+ 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':
@@ -1521,6 +1579,13 @@ def main():
else:
set_trisycl_include_dir(environ_cp)
+ set_action_env_var(environ_cp, 'TF_NEED_ROCM', 'ROCm', False)
+ if (environ_cp.get('TF_NEED_ROCM') == '1' and
+ 'LD_LIBRARY_PATH' in environ_cp and
+ environ_cp.get('LD_LIBRARY_PATH') != '1'):
+ write_action_env_to_bazelrc('LD_LIBRARY_PATH',
+ environ_cp.get('LD_LIBRARY_PATH'))
+
set_action_env_var(environ_cp, 'TF_NEED_CUDA', 'CUDA', False)
if (environ_cp.get('TF_NEED_CUDA') == '1' and
'TF_CUDA_CONFIG_REPO' not in environ_cp):
@@ -1561,36 +1626,56 @@ def main():
write_to_bazelrc('build --config=download_clang')
write_to_bazelrc('test --config=download_clang')
+ # SYCL / ROCm / CUDA are mutually exclusive.
+ # At most 1 GPU platform can be configured.
+ gpu_platform_count = 0
+ if environ_cp.get('TF_NEED_OPENCL_SYCL') == '1':
+ gpu_platform_count += 1
+ if environ_cp.get('TF_NEED_ROCM') == '1':
+ gpu_platform_count += 1
+ if environ_cp.get('TF_NEED_CUDA') == '1':
+ gpu_platform_count += 1
+ if gpu_platform_count >= 2:
+ raise UserInputError('SYCL / CUDA / ROCm are mututally exclusive. '
+ 'At most 1 GPU platform can be configured.')
+
set_build_var(environ_cp, 'TF_NEED_MPI', 'MPI', 'with_mpi_support', False)
if environ_cp.get('TF_NEED_MPI') == '1':
set_mpi_home(environ_cp)
set_other_mpi_vars(environ_cp)
- set_grpc_build_flags()
set_cc_opt_flags(environ_cp)
set_system_libs_flag(environ_cp)
if is_windows():
set_windows_build_flags(environ_cp)
- if get_var(
- environ_cp, 'TF_SET_ANDROID_WORKSPACE', 'android workspace',
- False,
- ('Would you like to interactively configure ./WORKSPACE for '
- 'Android builds?'),
- 'Searching for NDK and SDK installations.',
- 'Not configuring the WORKSPACE for Android builds.'):
+ # Add a config option to build TensorFlow 2.0 API.
+ write_to_bazelrc('build:v2 --define=tf_api_version=2')
+
+ if get_var(environ_cp, 'TF_SET_ANDROID_WORKSPACE', 'android workspace', False,
+ ('Would you like to interactively configure ./WORKSPACE for '
+ 'Android builds?'), 'Searching for NDK and SDK installations.',
+ 'Not configuring the WORKSPACE for Android builds.'):
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 tools/bazel.rc for '
- 'more details.')
- config_info_line('mkl', 'Build with MKL support.')
- config_info_line('monolithic', 'Config for mostly static monolithic build.')
+ 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 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__':
main()
+
diff --git a/tensorflow/BUILD b/tensorflow/BUILD
index 386e0096ff705c2eaa98f42833ef650bac6fc8d8..77e3baaff198b402dc04daa1b11e4007b9906b23 100644
--- a/tensorflow/BUILD
+++ b/tensorflow/BUILD
@@ -203,81 +203,46 @@ config_setting(
visibility = ["//visibility:public"],
)
-# TODO(jhseu): Enable on other platforms other than Linux.
-config_setting(
- name = "with_jemalloc_linux_x86_64",
- define_values = {"with_jemalloc": "true"},
- values = {"cpu": "k8"},
- visibility = ["//visibility:public"],
-)
-
-config_setting(
- name = "with_jemalloc_linux_ppc64le",
- define_values = {"with_jemalloc": "true"},
- values = {"cpu": "ppc"},
- visibility = ["//visibility:public"],
-)
-
config_setting(
name = "with_default_optimizations",
define_values = {"with_default_optimizations": "true"},
visibility = ["//visibility:public"],
)
+# Features that are default ON are handled differently below.
+#
config_setting(
- name = "with_gcp_support",
- define_values = {"with_gcp_support": "true"},
- visibility = ["//visibility:public"],
-)
-
-config_setting(
- name = "with_hdfs_support",
- define_values = {"with_hdfs_support": "true"},
- visibility = ["//visibility:public"],
-)
-
-config_setting(
- name = "with_aws_support",
- define_values = {"with_aws_support": "true"},
- visibility = ["//visibility:public"],
-)
-
-config_setting(
- name = "with_kafka_support",
- define_values = {"with_kafka_support": "true"},
+ name = "no_aws_support",
+ define_values = {"no_aws_support": "false"},
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_gcp_support_windows_override",
- define_values = {"with_gcp_support": "true"},
- values = {"cpu": "x64_windows"},
+ name = "no_gcp_support",
+ define_values = {"no_gcp_support": "false"},
visibility = ["//visibility:public"],
)
config_setting(
- name = "with_hdfs_support_windows_override",
- define_values = {"with_hdfs_support": "true"},
- values = {"cpu": "x64_windows"},
+ name = "no_hdfs_support",
+ define_values = {"no_hdfs_support": "false"},
visibility = ["//visibility:public"],
)
config_setting(
- name = "with_aws_support_windows_override",
- define_values = {"with_aws_support": "true"},
- values = {"cpu": "x64_windows"},
+ name = "no_ignite_support",
+ define_values = {"no_ignite_support": "false"},
visibility = ["//visibility:public"],
)
config_setting(
- name = "with_kafka_support_windows_override",
- define_values = {"with_kafka_support": "true"},
- values = {"cpu": "x64_windows"},
+ name = "no_kafka_support",
+ define_values = {"no_kafka_support": "false"},
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"},
@@ -285,48 +250,6 @@ config_setting(
visibility = ["//visibility:public"],
)
-config_setting(
- name = "with_gcp_support_android_override",
- define_values = {"with_gcp_support": "true"},
- values = {"crosstool_top": "//external:android/crosstool"},
- visibility = ["//visibility:public"],
-)
-
-config_setting(
- name = "with_hdfs_support_android_override",
- define_values = {"with_hdfs_support": "true"},
- values = {"crosstool_top": "//external:android/crosstool"},
- visibility = ["//visibility:public"],
-)
-
-config_setting(
- name = "with_aws_support_android_override",
- define_values = {"with_aws_support": "true"},
- values = {"crosstool_top": "//external:android/crosstool"},
- visibility = ["//visibility:public"],
-)
-
-config_setting(
- name = "with_gcp_support_ios_override",
- define_values = {"with_gcp_support": "true"},
- values = {"crosstool_top": "//tools/osx/crosstool:crosstool"},
- visibility = ["//visibility:public"],
-)
-
-config_setting(
- name = "with_hdfs_support_ios_override",
- define_values = {"with_hdfs_support": "true"},
- values = {"crosstool_top": "//tools/osx/crosstool:crosstool"},
- visibility = ["//visibility:public"],
-)
-
-config_setting(
- name = "with_aws_support_ios_override",
- define_values = {"with_aws_support": "true"},
- values = {"crosstool_top": "//tools/osx/crosstool:crosstool"},
- visibility = ["//visibility:public"],
-)
-
config_setting(
name = "with_xla_support",
define_values = {"with_xla_support": "true"},
@@ -355,30 +278,6 @@ config_setting(
visibility = ["//visibility:public"],
)
-config_setting(
- name = "with_jemalloc_linux_x86_64_dynamic",
- define_values = {
- "with_jemalloc": "true",
- "framework_shared_object": "true",
- },
- values = {
- "cpu": "k8",
- },
- visibility = ["//visibility:public"],
-)
-
-config_setting(
- name = "with_jemalloc_linux_ppc64le_dynamic",
- define_values = {
- "with_jemalloc": "true",
- "framework_shared_object": "true",
- },
- values = {
- "cpu": "ppc",
- },
- visibility = ["//visibility:public"],
-)
-
config_setting(
name = "using_cuda_clang",
define_values = {
@@ -564,6 +463,7 @@ tf_cc_shared_object(
"$(location //tensorflow/c:version_script.lds)",
],
}),
+ visibility = ["//visibility:public"],
deps = [
"//tensorflow/c:c_api",
"//tensorflow/c:c_api_experimental",
@@ -588,6 +488,7 @@ tf_cc_shared_object(
"$(location //tensorflow:tf_version_script.lds)",
],
}),
+ visibility = ["//visibility:public"],
deps = [
"//tensorflow:tf_exported_symbols.lds",
"//tensorflow:tf_version_script.lds",
@@ -608,6 +509,55 @@ exports_files(
],
)
+genrule(
+ name = "install_headers",
+ srcs = [
+ "//tensorflow/c:headers",
+ "//tensorflow/c/eager:headers",
+ "//tensorflow/cc:headers",
+ "//tensorflow/core:headers",
+ ],
+ outs = ["include"],
+ cmd = """
+ mkdir $@
+ for f in $(SRCS); do
+ d="$${f%/*}"
+ d="$${d#bazel-out*genfiles/}"
+ d="$${d#*external/eigen_archive/}"
+
+ if [[ $${d} == *local_config_* ]]; then
+ continue
+ fi
+
+ if [[ $${d} == external* ]]; then
+ extname="$${d#*external/}"
+ extname="$${extname%%/*}"
+ if [[ $${TF_SYSTEM_LIBS:-} == *$${extname}* ]]; then
+ continue
+ fi
+ fi
+
+ mkdir -p "$@/$${d}"
+ cp "$${f}" "$@/$${d}/"
+ done
+ """,
+ tags = ["manual"],
+ visibility = ["//visibility:public"],
+)
+
+genrule(
+ name = "root_init_gen",
+ srcs = select({
+ "api_version_2": [":tf_python_api_gen_v2"],
+ "//conditions:default": [":tf_python_api_gen_v1"],
+ }),
+ outs = ["__init__.py"],
+ cmd = select({
+ "api_version_2": "cp $(@D)/_api/v2/__init__.py $(OUTS)",
+ "//conditions:default": "cp $(@D)/_api/v1/__init__.py $(OUTS)",
+ }),
+)
+
gen_api_init_files(
name = "tf_python_api_gen_v1",
srcs = ["api_template.__init__.py"],
@@ -629,19 +579,6 @@ gen_api_init_files(
root_init_template = "api_template.__init__.py",
)
-genrule(
- name = "root_init_gen",
- srcs = select({
- "api_version_2": [":tf_python_api_gen_v2"],
- "//conditions:default": [":tf_python_api_gen_v1"],
- }),
- outs = ["__init__.py"],
- cmd = select({
- "api_version_2": "cp $(@D)/_api/v2/__init__.py $(OUTS)",
- "//conditions:default": "cp $(@D)/_api/v1/__init__.py $(OUTS)",
- }),
-)
-
py_library(
name = "tensorflow_py",
srcs = ["//tensorflow/python/estimator/api:estimator_python_api_gen"],
diff --git a/tensorflow/api_template.__init__.py b/tensorflow/api_template.__init__.py
index 53a72b84430ac703323e8235b4e3393d1c9898bc..2de740e145f93b151faf5c987808dbdf73fb4fd7 100644
--- a/tensorflow/api_template.__init__.py
+++ b/tensorflow/api_template.__init__.py
@@ -14,9 +14,9 @@
# ==============================================================================
"""Bring in all of the public TensorFlow interface into this module."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
+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
@@ -41,6 +41,11 @@ except (ImportError, AttributeError):
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
@@ -51,10 +56,6 @@ _tf_api_dir = _os.path.dirname(_os.path.dirname(app.__file__)) # pylint: disabl
if _tf_api_dir not in __path__:
__path__.append(_tf_api_dir)
-del absolute_import
-del division
-del print_function
-
# 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
diff --git a/tensorflow/c/BUILD b/tensorflow/c/BUILD
index 43c279bd800d79eeaf9a25bbc1978148f93c0a50..56f5e6767ac68b1008c786e3b5a47b9b173ab9cb 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
@@ -197,9 +198,9 @@ tf_cuda_cc_test(
size = "small",
srcs = ["c_api_test.cc"],
data = [
- ":test_op.so",
"//tensorflow/cc/saved_model:saved_model_half_plus_two",
],
+ kernels = [":test_op_kernel"],
linkopts = select({
"//tensorflow:darwin": ["-headerpad_max_install_names"],
"//conditions:default": [],
@@ -246,6 +247,7 @@ tf_cc_test(
":c_api_experimental",
":c_test_util",
"//tensorflow/core:lib",
+ "//tensorflow/core:protos_all_cc",
"//tensorflow/core:test",
"//tensorflow/core:test_main",
],
@@ -284,6 +286,16 @@ tf_custom_op_library(
srcs = ["test_op.cc"],
)
+tf_kernel_library(
+ name = "test_op_kernel",
+ srcs = ["test_op.cc"],
+ deps = [
+ "//tensorflow/core:framework",
+ "//tensorflow/core:lib",
+ ],
+ alwayslink = 1,
+)
+
# -----------------------------------------------------------------------------
# Python API target
diff --git a/tensorflow/c/c_api.cc b/tensorflow/c/c_api.cc
index 79811ceae57e0bddeb2a6f32bad7003e14e23422..1726db12fa62c5a3665de9fc306da38c1b7f0f9c 100644
--- a/tensorflow/c/c_api.cc
+++ b/tensorflow/c/c_api.cc
@@ -2770,6 +2770,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);
diff --git a/tensorflow/c/c_api_experimental.cc b/tensorflow/c/c_api_experimental.cc
index c195c9e01ca920c7234499b6e1d5e9cbf24056f3..d4b78138e93624a7e41e917f8210281b500661bc 100644
--- a/tensorflow/c/c_api_experimental.cc
+++ b/tensorflow/c/c_api_experimental.cc
@@ -23,6 +23,7 @@ limitations under the License.
#include "tensorflow/core/lib/strings/strcat.h"
#include "tensorflow/core/platform/platform.h"
#include "tensorflow/core/protobuf/config.pb.h"
+#include "tensorflow/core/protobuf/tensorflow_server.pb.h"
using tensorflow::FunctionDef;
using tensorflow::Node;
@@ -8508,6 +8509,20 @@ void TF_EnqueueNamedTensor(TF_Session* session, int tensor_id,
VLOG(1) << "Enqueuing is done.";
}
+TF_Buffer* TFE_GetServerDef(const char* text_proto, TF_Status* status) {
+ tensorflow::ServerDef server_def;
+ if (!tensorflow::protobuf::TextFormat::ParseFromString(text_proto,
+ &server_def)) {
+ status->status = tensorflow::errors::Internal(
+ "Invalid text proto for ServerDef: ", text_proto);
+ return nullptr;
+ }
+ status->status = tensorflow::Status();
+ TF_Buffer* ret = TF_NewBuffer();
+ TF_CHECK_OK(MessageToBuffer(server_def, ret));
+ return ret;
+}
+
TFE_Context* TFE_CreateContextFromSession(TF_Session* session,
TF_Status* status) {
auto* opts = TFE_NewContextOptions();
@@ -8705,3 +8720,25 @@ TFE_TensorHandle* TFE_DequeueVariantTensor(TF_Session* session, int tensor_id,
return createTFEDequeue(ctx, TF_VARIANT, queue, status);
}
+
+static void CheckOk(TF_Status* status) {
+ CHECK_EQ(TF_GetCode(status), TF_OK) << TF_Message(status);
+}
+
+void TFE_TensorHandlePrintDebugString(TFE_TensorHandle* handle) {
+ auto* status = TF_NewStatus();
+ TF_Tensor* t = TFE_TensorHandleResolve(handle, status);
+ CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status);
+
+ tensorflow::Tensor dst;
+ TF_CHECK_OK(TF_TensorToTensor(t, &dst));
+ LOG(INFO) << dst.DebugString();
+
+ TF_DeleteTensor(t);
+ TF_DeleteStatus(status);
+}
+
+TF_CAPI_EXPORT extern void TF_MakeInternalErrorStatus(TF_Status* status,
+ const char* errMsg) {
+ status->status = tensorflow::errors::Internal(errMsg);
+}
diff --git a/tensorflow/c/c_api_experimental.h b/tensorflow/c/c_api_experimental.h
index 522c91f67efdf10118268842dee3beb334fb720d..d98d532e32e891e21f5b7ba360c74c3256fb1947 100644
--- a/tensorflow/c/c_api_experimental.h
+++ b/tensorflow/c/c_api_experimental.h
@@ -131,6 +131,8 @@ TF_CAPI_EXPORT extern void TF_EnqueueNamedTensor(TF_Session* session,
int tensor_id,
TF_Tensor* tensor,
TF_Status* status);
+// Create a serialized tensorflow.ServerDef proto.
+TF_Buffer* TFE_GetServerDef(const char* text_proto, TF_Status* status);
// TODO: remove this API in favor of the next one.
TF_CAPI_EXPORT extern TFE_Context* TFE_NewContextFromSession(
@@ -174,6 +176,13 @@ TF_CAPI_EXPORT extern void TFE_EnqueueVariantTensor(TF_Session* session,
TF_CAPI_EXPORT extern TFE_TensorHandle* TFE_DequeueVariantTensor(
TF_Session* session, int tensor_id, TF_Status* status);
+// Prints `handle` in a human readable format to standard output for debugging.
+TF_CAPI_EXPORT extern void TFE_TensorHandlePrintDebugString(
+ TFE_TensorHandle* handle);
+
+TF_CAPI_EXPORT extern void TF_MakeInternalErrorStatus(TF_Status* status,
+ const char* errMsg);
+
#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 30fcfd401d9d634962d64aaa3bf348de91f2ecae..c6effd39697e0397278770b53e98508074f99862 100644
--- a/tensorflow/c/c_api_experimental_test.cc
+++ b/tensorflow/c/c_api_experimental_test.cc
@@ -16,8 +16,10 @@ limitations under the License.
#include "tensorflow/c/c_api_experimental.h"
#include "tensorflow/c/c_test_util.h"
#include "tensorflow/core/lib/io/path.h"
+#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/test.h"
+#include "tensorflow/core/protobuf/tensorflow_server.pb.h"
namespace tensorflow {
namespace {
@@ -116,5 +118,49 @@ TEST(CAPI_EXPERIMENTAL, ImagenetIteratorGetNext) {
TF_DeleteStatus(s);
}
+TEST(CAPI_EXPERIMENTAL, GetServerDefTest) {
+ const string expected_text_proto(R"(cluster {
+ job {
+ name: "worker"
+ tasks {
+ key: 0
+ value: "tpuserver:0"
+ }
+ tasks {
+ key: 1
+ value: "localhost:1"
+ }
+ }
+}
+job_name: "worker"
+task_index: 1
+protocol: "grpc"
+)");
+
+ TF_Status* status = TF_NewStatus();
+ TF_Buffer* result = TFE_GetServerDef(expected_text_proto.c_str(), status);
+ EXPECT_EQ(TF_GetCode(status), TF_OK);
+
+ ServerDef actual;
+ ASSERT_TRUE(actual.ParseFromArray(result->data, result->length));
+ string actual_text_proto;
+ tensorflow::protobuf::TextFormat::PrintToString(actual, &actual_text_proto);
+ EXPECT_EQ(expected_text_proto, actual_text_proto);
+
+ const string malformed_text_proto(R"(cluster {
+ job {
+ name: "worker")");
+ TF_Buffer* null_result =
+ TFE_GetServerDef(malformed_text_proto.c_str(), status);
+ EXPECT_NE(TF_GetCode(status), TF_OK);
+ EXPECT_TRUE(tensorflow::str_util::StrContains(
+ TF_Message(status), "Invalid text proto for ServerDef"));
+ EXPECT_EQ(null_result, nullptr);
+
+ // Cleanup
+ TF_DeleteBuffer(result);
+ TF_DeleteStatus(status);
+}
+
} // namespace
} // namespace tensorflow
diff --git a/tensorflow/c/c_api_test.cc b/tensorflow/c/c_api_test.cc
index 03516c39dc970aa23967107d3a0446da94669465..c4746b4990bc3bf80b749428f803056e552421c3 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"
@@ -195,12 +196,31 @@ TEST(CAPI, LibraryLoadFunctions) {
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_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);
+ }
+
+#if !defined(TENSORFLOW_NO_SHARED_OBJECTS)
+ {
+ // 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());
+ }
+#endif // !defined(TENSORFLOW_NO_SHARED_OBJECTS)
TF_DeleteLibraryHandle(lib);
}
@@ -2335,9 +2355,9 @@ TEST(TestApiDef, TestCreateApiDef) {
EXPECT_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status);
TF_DeleteStatus(status);
- TF_Buffer op_list_buf = TF_GetOpList(lib);
+ TF_Buffer* op_list_buf = TF_GetAllOpList();
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,6 +2375,7 @@ TEST(TestApiDef, TestCreateApiDef) {
TF_DeleteBuffer(api_def_buf);
TF_DeleteApiDefMap(api_def_map);
+ TF_DeleteBuffer(op_list_buf);
TF_DeleteLibraryHandle(lib);
}
@@ -2369,9 +2390,9 @@ TEST(TestApiDef, TestCreateApiDefWithOverwrites) {
EXPECT_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status);
TF_DeleteStatus(status);
- TF_Buffer op_list_buf = TF_GetOpList(lib);
+ TF_Buffer* op_list_buf = TF_GetAllOpList();
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,6 +2421,7 @@ TEST(TestApiDef, TestCreateApiDefWithOverwrites) {
TF_DeleteBuffer(api_def_buf);
TF_DeleteApiDefMap(api_def_map);
+ TF_DeleteBuffer(op_list_buf);
TF_DeleteLibraryHandle(lib);
}
diff --git a/tensorflow/c/eager/BUILD b/tensorflow/c/eager/BUILD
index 37be52f57d865c1e59611540d5dab04b59e89444..3ee31a6a7ac641bbd3fc4c05568b61e433a1d523 100644
--- a/tensorflow/c/eager/BUILD
+++ b/tensorflow/c/eager/BUILD
@@ -68,7 +68,10 @@ tf_cuda_library(
tf_cuda_library(
name = "c_api_internal",
hdrs = ["c_api_internal.h"],
- visibility = ["//tensorflow:internal"],
+ visibility = [
+ "//learning/deepmind/courier:__pkg__",
+ "//tensorflow:internal",
+ ],
deps = [
":c_api",
"//tensorflow/c:c_api",
diff --git a/tensorflow/c/eager/c_api.cc b/tensorflow/c/eager/c_api.cc
index 349d9bcd7ca3991c7c3621f347af6025778612b7..3554ec0bf3202b54bfc38d67e51b89df19832302 100755
--- a/tensorflow/c/eager/c_api.cc
+++ b/tensorflow/c/eager/c_api.cc
@@ -375,6 +375,17 @@ int TFE_TensorHandleNumDims(TFE_TensorHandle* h, TF_Status* status) {
return result;
}
+int64_t TFE_TensorHandleNumElements(TFE_TensorHandle* h, TF_Status* status) {
+ if (h == nullptr || h->handle == nullptr) {
+ status->status = tensorflow::errors::InvalidArgument(
+ "The passed in handle is a nullptr");
+ return -1;
+ }
+ tensorflow::int64 result;
+ status->status = h->handle->NumElements(&result);
+ return result;
+}
+
int64_t TFE_TensorHandleDim(TFE_TensorHandle* h, int dim_index,
TF_Status* status) {
if (h == nullptr || h->handle == nullptr) {
@@ -567,6 +578,21 @@ void TFE_OpSetAttrFunction(TFE_Op* op, const char* attr_name,
op->operation.MutableAttrs()->Set(attr_name, attr_value);
}
+void TFE_OpSetAttrFunctionName(TFE_Op* op, const char* attr_name,
+ const char* data, size_t length) {
+ tensorflow::AttrValue attr_value;
+ tensorflow::NameAttrList* func = attr_value.mutable_func();
+ func->set_name(data, length);
+ op->operation.MutableAttrs()->Set(attr_name, attr_value);
+}
+
+void TFE_OpSetAttrTensor(TFE_Op* op, const char* attr_name, TF_Tensor* tensor,
+ TF_Status* status) {
+ tensorflow::Tensor t;
+ status->status = TF_TensorToTensor(tensor, &t);
+ if (status->status.ok()) op->operation.MutableAttrs()->Set(attr_name, t);
+}
+
void TFE_OpSetAttrStringList(TFE_Op* op, const char* attr_name,
const void* const* values, const size_t* lengths,
int num_values) {
diff --git a/tensorflow/c/eager/c_api.h b/tensorflow/c/eager/c_api.h
index 337447eec9581b01fa775affc49097986824a360..b2454d872207e26feb3764671474a5d87c01f84d 100755
--- a/tensorflow/c/eager/c_api.h
+++ b/tensorflow/c/eager/c_api.h
@@ -163,6 +163,8 @@ TF_CAPI_EXPORT extern TF_DataType TFE_TensorHandleDataType(TFE_TensorHandle* h);
// This function will block till the operation that produces `h` has completed.
TF_CAPI_EXPORT extern int TFE_TensorHandleNumDims(TFE_TensorHandle* h,
TF_Status* status);
+TF_CAPI_EXPORT extern int64_t TFE_TensorHandleNumElements(TFE_TensorHandle* h,
+ TF_Status* status);
// This function will block till the operation that produces `h` has completed.
TF_CAPI_EXPORT extern int64_t TFE_TensorHandleDim(TFE_TensorHandle* h,
int dim_index,
@@ -311,6 +313,14 @@ TF_CAPI_EXPORT extern void TFE_OpSetAttrFunction(TFE_Op* op,
const char* attr_name,
const TFE_Op* value);
+TF_CAPI_EXPORT void TFE_OpSetAttrFunctionName(TFE_Op* op, const char* attr_name,
+ const char* data, size_t length);
+
+TF_CAPI_EXPORT extern void TFE_OpSetAttrTensor(TFE_Op* op,
+ const char* attr_name,
+ TF_Tensor* tensor,
+ TF_Status* status);
+
TF_CAPI_EXPORT extern void TFE_OpSetAttrStringList(TFE_Op* op,
const char* attr_name,
const void* const* values,
diff --git a/tensorflow/c/eager/c_api_test_util.cc b/tensorflow/c/eager/c_api_test_util.cc
index 5607c9dcb0bbec72b2f86def3dd4e6590d73197b..008f088c2dcdd7d9114103516a4702e47a55c6de 100644
--- a/tensorflow/c/eager/c_api_test_util.cc
+++ b/tensorflow/c/eager/c_api_test_util.cc
@@ -99,8 +99,6 @@ TFE_Op* MatMulOp(TFE_Context* ctx, TFE_TensorHandle* a, TFE_TensorHandle* b) {
TFE_OpAddInput(op, b, status);
CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status);
TF_DeleteStatus(status);
- TFE_OpSetAttrBool(op, "transpose_a", 0);
- TFE_OpSetAttrBool(op, "transpose_b", 0);
TFE_OpSetAttrType(op, "T", TFE_TensorHandleDataType(a));
return op;
diff --git a/tensorflow/c/eager/tape.h b/tensorflow/c/eager/tape.h
index ce038a4b57b2699c6d09fcf75ef41cecec4e97b8..5ba55a203ff70cc64c07e96b5a869a1f11c9334e 100644
--- a/tensorflow/c/eager/tape.h
+++ b/tensorflow/c/eager/tape.h
@@ -29,15 +29,8 @@ limitations under the License.
namespace tensorflow {
namespace eager {
-// Information about a tensor.
-struct TapeTensor {
- int64 id; // Expected to be unique in the lifetime of this process.
- DataType dtype;
- TensorShape shape;
-};
-
// Represents an entry in the tape.
-template
+template
struct OpTapeEntry {
string op_type;
std::vector output_tensor_info;
@@ -57,8 +50,8 @@ struct OpTapeEntry {
using TensorTape = gtl::FlatMap;
// Map from operation-id to tape entry.
-template
-using OpTape = gtl::FlatMap>;
+template
+using OpTape = gtl::FlatMap>;
// Operations the tape needs to perform on tensors to do backpropagation. Named
// "vspace" because a subset of these are related to a vector space, such as
@@ -79,7 +72,7 @@ using OpTape = gtl::FlatMap>;
// TODO(apassos) provide concrete template instantiations for TFE_TensorHandle
// specialization, which is blocked by quite a few things needing to loop back
// into python now.
-template
+template
class VSpace {
public:
virtual ~VSpace() {}
@@ -93,10 +86,10 @@ class VSpace {
gtl::ArraySlice gradient_tensors) const = 0;
// Returns a tensor of the right shape and dtype filled with zeros.
- virtual Gradient* Zeros(TensorShape shape, DataType dtype) const = 0;
+ virtual Gradient* Zeros(const TapeTensor& tensor) const = 0;
// Returns a Tensor which is filled with ones and like the input.
- virtual Gradient* Ones(TensorShape shape, DataType dtype) const = 0;
+ virtual Gradient* Ones(const TapeTensor& tensor) const = 0;
// Calls the passed-in backward function.
virtual Status CallBackwardFunction(
@@ -114,7 +107,7 @@ class VSpace {
// Traces the execution of operations, doing eager garbage collection, and
// exporting a full trace so other code can do backpropagation. Not thread-safe.
-template
+template
class GradientTape {
public:
// If `persistent` is true, GradientTape will not eagerly delete backward
@@ -134,10 +127,10 @@ class GradientTape {
void Watch(int64 tensor_id);
void RecordOperation(
- const string& op_type, gtl::ArraySlice output_tensors,
+ const string& op_type, std::vector& output_tensors,
gtl::ArraySlice input_tensor_id,
gtl::ArraySlice input_dtypes,
- BackwardFunction* backward_function,
+ const std::function& backward_function_getter,
const std::function& backward_function_deleter);
void DeleteTrace(int64 tensor_id);
@@ -146,17 +139,18 @@ class GradientTape {
// once) and produces the gradient of the target tensors with respect to the
// source tensors. The output gradients are used if not empty and not
// 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,
- gtl::ArraySlice output_gradients,
- std::vector* result);
+ Status ComputeGradient(
+ const VSpace& vspace,
+ gtl::ArraySlice target_tensor_ids,
+ gtl::ArraySlice source_tensor_id,
+ gtl::ArraySlice output_gradients,
+ std::vector* result);
bool IsPersistent() const { return persistent_; }
private:
TensorTape tensor_tape_;
- OpTape op_tape_;
+ OpTape op_tape_;
int64 next_op_id_{0};
// Map from tensor id to number of remaining usages (i.e. how many entries in
@@ -186,8 +180,8 @@ inline bool IsDtypeTrainable(DataType dtype) {
}
}
-template
-bool GradientTape::ShouldRecord(
+template
+bool GradientTape::ShouldRecord(
gtl::ArraySlice tensor_ids,
gtl::ArraySlice dtypes) {
CHECK_EQ(tensor_ids.size(), dtypes.size());
@@ -201,20 +195,20 @@ bool GradientTape::ShouldRecord(
return false;
}
-template
-void GradientTape::Watch(int64 tensor_id) {
+template
+void GradientTape::Watch(
+ int64 tensor_id) {
tensor_tape_.emplace(tensor_id, -1);
}
-template
-void GradientTape::RecordOperation(
- const string& op_type, gtl::ArraySlice output_tensors,
+template
+void GradientTape::RecordOperation(
+ const string& op_type, std::vector& output_tensors,
gtl::ArraySlice input_tensor_id,
gtl::ArraySlice input_dtypes,
- BackwardFunction* backward_function,
+ const std::function& backward_function_getter,
const std::function& backward_function_deleter) {
if (!ShouldRecord(input_tensor_id, input_dtypes)) {
- backward_function_deleter(backward_function);
return;
}
std::vector ids;
@@ -229,16 +223,18 @@ void GradientTape::RecordOperation(
for (const TapeTensor& o : output_tensors) {
// Note: the tensor can have already been watched and hence be in the tape,
// so we cannot check that we're inserting it here.
- tensor_tape_[o.id] = op_id;
- tensor_usage_[o.id] = 1;
+ tensor_tape_[o.GetID()] = op_id;
+ tensor_usage_[o.GetID()] = 1;
tensors.push_back(o);
}
- op_tape_[op_id] = OpTapeEntry{
- op_type, tensors, ids, backward_function, backward_function_deleter};
+ op_tape_[op_id] = OpTapeEntry{
+ op_type, std::move(tensors), std::move(ids), backward_function_getter(),
+ backward_function_deleter};
}
-template
-void GradientTape::DeleteTrace(int64 tensor_id) {
+template
+void GradientTape::DeleteTrace(
+ int64 tensor_id) {
auto it = tensor_usage_.find(tensor_id);
if (it == tensor_usage_.end()) {
return;
@@ -261,7 +257,7 @@ void GradientTape::DeleteTrace(int64 tensor_id) {
auto op_it = op_tape_.find(op_id);
CHECK(op_it != op_tape_.end());
for (const auto& output : op_it->second.output_tensor_info) {
- if (tensor_usage_.find(output.id) != tensor_usage_.end()) {
+ if (tensor_usage_.find(output.GetID()) != tensor_usage_.end()) {
// Found a usage for an output, so cannot delete the op.
return;
}
@@ -304,9 +300,9 @@ void GradientTape::DeleteTrace(int64 tensor_id) {
namespace {
-template
+template
struct BackpropInitialState {
- OpTape op_tape;
+ OpTape op_tape;
// Map from tensor ID to how many references still exist for this tensor in
// the tape.
@@ -322,17 +318,17 @@ struct BackpropInitialState {
// If `persistent_tape` is false, op_tape is cleared and backwards functions
// not needed for gradient computation are deleted. Backwards functions that
// are needed, are copied and returned in BackpropInitialState.
-template
-BackpropInitialState PrepareBackprop(
+template
+BackpropInitialState PrepareBackprop(
gtl::ArraySlice target, const TensorTape& tensor_tape,
- OpTape* op_tape, const gtl::FlatSet& sources_set,
- bool persistent_tape) {
+ OpTape* op_tape,
+ const gtl::FlatSet& sources_set, bool persistent_tape) {
std::vector tensor_stack;
tensor_stack.reserve(target.size());
for (auto t : target) {
tensor_stack.push_back(t);
}
- BackpropInitialState result;
+ BackpropInitialState result;
while (!tensor_stack.empty()) {
int64 tensor_id = tensor_stack.back();
tensor_stack.pop_back();
@@ -383,9 +379,9 @@ BackpropInitialState PrepareBackprop(
return result;
}
-template
+template
std::vector InitialStack(
- const OpTape& op_tape,
+ const OpTape& op_tape,
const gtl::FlatMap& op_missing_tensor) {
std::vector result;
for (auto& op_entry : op_tape) {
@@ -396,13 +392,13 @@ std::vector InitialStack(
return result;
}
-template
-Status InitialGradients(const VSpace& vspace,
- gtl::ArraySlice target_tensor_ids,
- gtl::ArraySlice output_gradients,
- const TensorTape& tensor_tape,
- const OpTape& op_tape,
- gtl::FlatMap>* result) {
+template
+Status InitialGradients(
+ const VSpace& vspace,
+ gtl::ArraySlice target_tensor_ids,
+ gtl::ArraySlice output_gradients, const TensorTape& tensor_tape,
+ const OpTape& op_tape,
+ gtl::FlatMap>* result) {
for (int i = 0; i < target_tensor_ids.size(); ++i) {
const int64 id = target_tensor_ids[i];
if (output_gradients.empty() || output_gradients[i] == nullptr) {
@@ -416,11 +412,10 @@ Status InitialGradients(const VSpace& vspace,
}
bool found = false;
for (int j = 0; j < op_it->second.output_tensor_info.size(); ++j) {
- if (op_it->second.output_tensor_info[j].id == id) {
+ if (op_it->second.output_tensor_info[j].GetID() == id) {
found = true;
(*result)[id].push_back(
- vspace.Ones(op_it->second.output_tensor_info[j].shape,
- op_it->second.output_tensor_info[j].dtype));
+ vspace.Ones(op_it->second.output_tensor_info[j]));
break;
}
}
@@ -440,6 +435,18 @@ Status InitialGradients(const VSpace& vspace,
return Status::OK();
}
+// TODO(agarwal): use an automatic mechanism for handling None arguments to
+// gradient functions.
+//
+// Some gradient functions can accept None arguments for gradients. The
+// following maps the operation name to the indices at which the corresponding
+// gradient function can accept None values. e.g. FusedBatchNorm outputs 5
+// values and hence receives 5 gradient values during backprop. However the
+// gradient function uses only the first of those values and ignores the rest.
+// The entry, "FusedBatchNorm": [1, 2, 3, 4], indicates that only the gradient
+// corresponding to index 0 is used, and the gradient values at indices 1-4 are
+// ignored (and hence can be None). The backprop algorithm can then leverage
+// this by not constructing zeros to pass for those indices.
gtl::FlatMap>* FunctionsAcceptingNoneForIndicesMap() {
static auto* const m = new gtl::FlatMap>({
{"SoftmaxCrossEntropyWithLogits", {1}},
@@ -457,16 +464,16 @@ gtl::FlatMap>* FunctionsAcceptingNoneForIndicesMap() {
constexpr int kMinAggregateCount = 4;
constexpr int kMinAggregateBytes = 128 * 1024 * 1024;
-template
-Status GradientTape::ComputeGradient(
- const VSpace& vspace,
+template
+Status GradientTape::ComputeGradient(
+ const VSpace& vspace,
gtl::ArraySlice target_tensor_ids,
gtl::ArraySlice source_tensor_ids,
gtl::ArraySlice output_gradients,
std::vector* result) {
gtl::FlatSet sources_set(source_tensor_ids.begin(),
source_tensor_ids.end());
- BackpropInitialState state = PrepareBackprop(
+ BackpropInitialState state = PrepareBackprop(
target_tensor_ids, tensor_tape_, &op_tape_, sources_set, persistent_);
std::vector op_stack =
InitialStack(state.op_tape, state.op_missing_tensor);
@@ -510,7 +517,7 @@ Status GradientTape::ComputeGradient(
out_gradients.reserve(trace.output_tensor_info.size());
bool any_gradient_nonzero = false;
for (int i = 0; i < trace.output_tensor_info.size(); ++i) {
- const int64 id = trace.output_tensor_info[i].id;
+ const int64 id = trace.output_tensor_info[i].GetID();
auto grad_it = gradients.find(id);
if (grad_it == gradients.end()) {
auto func_name_it =
@@ -519,9 +526,7 @@ Status GradientTape::ComputeGradient(
func_name_it->second.find(i) != func_name_it->second.end()) {
out_gradients.push_back(nullptr);
} else {
- out_gradients.push_back(
- vspace.Zeros(trace.output_tensor_info[i].shape,
- trace.output_tensor_info[i].dtype));
+ out_gradients.push_back(vspace.Zeros(trace.output_tensor_info[i]));
}
} else {
any_gradient_nonzero = true;
diff --git a/tensorflow/c/python_api.cc b/tensorflow/c/python_api.cc
index 8486b585c8587e18e8eea18a893fac0a40ff4a27..247236b760dd8c07bbb08426100b6a4d34296d2e 100644
--- a/tensorflow/c/python_api.cc
+++ b/tensorflow/c/python_api.cc
@@ -110,7 +110,7 @@ void ExtendSession(TF_Session* session, TF_Status* status) {
session->extend_before_run = false;
}
-std::string GetResourceHandleShapeAndType(TF_Graph* graph, TF_Output output) {
+std::string GetHandleShapeAndType(TF_Graph* graph, TF_Output output) {
Node* node = &output.oper->node;
CppShapeInferenceResult::HandleData handle_data;
handle_data.set_is_set(true);
@@ -135,9 +135,8 @@ std::string GetResourceHandleShapeAndType(TF_Graph* graph, TF_Output output) {
return result;
}
-void SetResourceHandleShapeAndType(TF_Graph* graph, TF_Output output,
- const void* proto, size_t proto_len,
- TF_Status* status) {
+void SetHandleShapeAndType(TF_Graph* graph, TF_Output output, const void* proto,
+ size_t proto_len, TF_Status* status) {
tensorflow::CppShapeInferenceResult::HandleData handle_data;
if (!handle_data.ParseFromArray(proto, proto_len)) {
status->status = tensorflow::errors::InvalidArgument(
diff --git a/tensorflow/c/python_api.h b/tensorflow/c/python_api.h
index 4bcb5bde62c8a4df4e68c1ce0daaf459434ceb5d..5cce84020bc68d912d259f51512341eb5f464a2c 100644
--- a/tensorflow/c/python_api.h
+++ b/tensorflow/c/python_api.h
@@ -54,16 +54,17 @@ void SetRequireShapeInferenceFns(TF_Graph* graph, bool require);
void ExtendSession(TF_Session* session, TF_Status* status);
// Returns the serialized CppShapeInferenceResult::HandleData proto for
-// `output` if its a resource tensor, or otherwise returns the empty string.
-std::string GetResourceHandleShapeAndType(TF_Graph* graph, TF_Output output);
+// `output` if its a resource or variant tensor, or otherwise returns the empty
+// string.
+std::string GetHandleShapeAndType(TF_Graph* graph, TF_Output output);
// Sets `output` based on `proto`, which should be a serialized
-// CppShapeInferenceResult::HandleData proto.
+// CppShapeInferenceResult::HandleData proto. `output` should be a resource
+// or variant tensor.
// NOTE(skyewm): `proto` is passed a void*/size_t pair instead of a std::string
// because I couldn't get SWIG to work otherwise.
-void SetResourceHandleShapeAndType(TF_Graph* graph, TF_Output output,
- const void* proto, size_t proto_len,
- TF_Status* status);
+void SetHandleShapeAndType(TF_Graph* graph, TF_Output output, const void* proto,
+ size_t proto_len, TF_Status* status);
} // namespace tensorflow
#endif // TENSORFLOW_C_PYTHON_API_H_
diff --git a/tensorflow/cc/BUILD b/tensorflow/cc/BUILD
index f56521dac0374849081fe94f16feb08e55647b56..c18b07603ae3841d3581741ab5a43f2e8b628356 100644
--- a/tensorflow/cc/BUILD
+++ b/tensorflow/cc/BUILD
@@ -10,11 +10,12 @@ licenses(["notice"]) # Apache 2.0
load(
"//tensorflow:tensorflow.bzl",
- "tf_cc_test",
+ "cc_library_with_android_deps",
"tf_cc_binary",
+ "tf_cc_test",
"tf_copts",
"tf_gen_op_wrappers_cc",
- "cc_library_with_android_deps",
+ "transitive_hdrs",
)
cc_library(
@@ -410,6 +411,7 @@ tf_cc_test(
srcs = ["gradients/nn_grad_test.cc"],
deps = [
":cc_ops",
+ ":cc_ops_internal",
":grad_op_registry",
":grad_testutil",
":gradient_checker",
@@ -452,11 +454,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",
@@ -467,7 +491,6 @@ tf_gen_op_wrappers_cc(
"logging_ops",
"lookup_ops",
"manip_ops",
- "math_ops",
"nn_ops",
"no_op",
"parsing_ops",
@@ -479,10 +502,21 @@ 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",
+ ],
)
tf_cc_test(
@@ -716,3 +750,26 @@ tf_cc_test(
"//tensorflow/core:testlib",
],
)
+
+transitive_hdrs(
+ name = "headers",
+ visibility = ["//tensorflow:__subpackages__"],
+ deps = [
+ ":cc_ops",
+ ":client_session",
+ ":coordinator",
+ ":gradient_checker",
+ ":gradients",
+ ":ops",
+ ":queue_runner",
+ ":remote_fused_graph_ops",
+ ":scope",
+ "//tensorflow/cc/profiler",
+ "//tensorflow/cc/saved_model:constants",
+ "//tensorflow/cc/saved_model:loader",
+ "//tensorflow/cc/saved_model:reader",
+ "//tensorflow/cc/saved_model:signature_constants",
+ "//tensorflow/cc/saved_model:tag_constants",
+ "//tensorflow/cc/tools:freeze_saved_model",
+ ],
+)
diff --git a/tensorflow/cc/framework/cc_op_gen.cc b/tensorflow/cc/framework/cc_op_gen.cc
index a32d1b1eb50fc715084f5ee663a732770db1883c..39593370d1c243e84dc5b6091724d1d404c102b0 100644
--- a/tensorflow/cc/framework/cc_op_gen.cc
+++ b/tensorflow/cc/framework/cc_op_gen.cc
@@ -853,11 +853,7 @@ void OpInfo::WriteClassDecl(WritableFile* h) const {
}
}
- strings::StrAppend(&class_decl, "\n");
-
- if (output_types.empty()) {
- strings::StrAppend(&class_decl, " Operation operation;\n");
- }
+ strings::StrAppend(&class_decl, "\n Operation operation;\n");
for (int i = 0; i < output_types.size(); ++i) {
strings::StrAppend(&class_decl, " ", output_types[i], " ", output_names[i],
";\n");
@@ -878,9 +874,11 @@ void OpInfo::GetOutput(string* out) const {
string return_on_error =
strings::StrCat("if (!", scope_str, ".ok()) return;");
+ strings::StrAppend(out, " this->operation = Operation(ret);\n");
+
// No outputs.
if (graph_op_def.output_arg_size() == 0) {
- strings::StrAppend(out, " this->operation = Operation(ret);\n return;\n");
+ strings::StrAppend(out, " return;\n");
return;
}
if (graph_op_def.output_arg_size() == 1) {
diff --git a/tensorflow/cc/framework/scope.cc b/tensorflow/cc/framework/scope.cc
index 7f6ac4cae78d8d6e118837fce9ae5270336cdc89..6abc9e268e3ac97379954a34017ddffa010db67f 100644
--- a/tensorflow/cc/framework/scope.cc
+++ b/tensorflow/cc/framework/scope.cc
@@ -62,7 +62,7 @@ Scope::Impl::Impl(const std::shared_ptr& graph,
refiner_(refiner),
scope_used_(nullptr),
colocation_constraints_(),
- disable_shape_inference_(false) {}
+ disable_shape_inference_(refiner_ == nullptr) {}
Scope Scope::NewRootScope() {
Graph* graph = new Graph(OpRegistry::Global());
@@ -94,6 +94,7 @@ Scope::Impl::Impl(const Scope& other, Tags::ScopeName, const string& 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_),
colocation_constraints_(other.impl()->colocation_constraints_),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
@@ -110,6 +111,7 @@ Scope::Impl::Impl(const Scope& other, Tags::OpName, const string& 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_),
colocation_constraints_(other.impl()->colocation_constraints_),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
@@ -132,6 +134,7 @@ Scope::Impl::Impl(const Scope& other, Tags::ControlDeps,
exit_on_error_(other.impl()->exit_on_error_),
kernel_label_(other.impl()->kernel_label_),
device_(other.impl()->device_),
+ assigned_device_(other.impl()->assigned_device_),
colocation_constraints_(other.impl()->colocation_constraints_),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
@@ -163,6 +166,7 @@ Scope::Impl::Impl(const Scope& other, Tags::SingleUseScope,
exit_on_error_(other.impl()->exit_on_error_),
kernel_label_(other.impl()->kernel_label_),
device_(other.impl()->device_),
+ assigned_device_(other.impl()->assigned_device_),
colocation_constraints_(other.impl()->colocation_constraints_),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
@@ -178,6 +182,7 @@ Scope::Impl::Impl(const Scope& other, Tags::ExitOnError)
exit_on_error_(true),
kernel_label_(other.impl()->kernel_label_),
device_(other.impl()->device_),
+ assigned_device_(other.impl()->assigned_device_),
colocation_constraints_(other.impl()->colocation_constraints_),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
@@ -194,6 +199,7 @@ Scope::Impl::Impl(const Scope& other, Tags::KernelLabel,
exit_on_error_(other.impl()->exit_on_error_),
kernel_label_(kernel_label),
device_(other.impl()->device_),
+ assigned_device_(other.impl()->assigned_device_),
colocation_constraints_(other.impl()->colocation_constraints_),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
@@ -210,12 +216,30 @@ Scope::Impl::Impl(const Scope& other, Tags::Colocate,
exit_on_error_(other.impl()->exit_on_error_),
kernel_label_(other.impl()->kernel_label_),
device_(other.impl()->device_),
+ assigned_device_(other.impl()->assigned_device_),
colocation_constraints_(
clear_colocations
? std::unordered_set()
: other.impl()->GetColocationConstraints(colocate_with_op)),
disable_shape_inference_(other.impl()->disable_shape_inference_) {}
+Scope::Impl::Impl(const Scope& other, Tags::AssignedDevice,
+ const string& assigned_device)
+ : 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_(assigned_device),
+ colocation_constraints_(other.impl()->colocation_constraints_),
+ disable_shape_inference_(other.impl()->disable_shape_inference_) {}
+
std::unordered_set Scope::Impl::GetColocationConstraints(
const Operation& colocate_with_op) const {
std::unordered_set current_constraints(colocation_constraints_);
@@ -299,6 +323,9 @@ void Scope::UpdateBuilder(NodeBuilder* builder) const {
if (!impl()->device_.empty()) {
builder->Device(impl()->device_);
}
+ if (!impl()->assigned_device_.empty()) {
+ builder->AssignedDevice(impl()->assigned_device_);
+ }
}
string Scope::Impl::GetUniqueName(const string& prefix,
@@ -394,6 +421,10 @@ Scope Scope::WithDevice(const string& device) const {
return Scope(new Impl(*this, Impl::Tags::Device(), device));
}
+Scope Scope::WithAssignedDevice(const string& assigned_device) const {
+ return Scope(new Impl(*this, Impl::Tags::AssignedDevice(), assigned_device));
+}
+
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 30c32bd44b0f22d6b29dd3836d431807d0216818..e307d8989b6647dfac8d2691ed2171c86b7f3a7c 100644
--- a/tensorflow/cc/framework/scope.h
+++ b/tensorflow/cc/framework/scope.h
@@ -133,6 +133,10 @@ class Scope {
/// the device field set to 'device'.
Scope WithDevice(const string& device) const;
+ /// Returns a new scope. All ops created within the returned scope will have
+ /// their assigned device set to `assigned_device`.
+ Scope WithAssignedDevice(const string& assigned_device) 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
diff --git a/tensorflow/cc/framework/scope_internal.h b/tensorflow/cc/framework/scope_internal.h
index 58adaef2e942a7fa6b0ce8d5534ac3e2fd380580..514e02e84146b6d95147d83182e5d9a07509cfa1 100644
--- a/tensorflow/cc/framework/scope_internal.h
+++ b/tensorflow/cc/framework/scope_internal.h
@@ -26,6 +26,8 @@ class ShapeRefiner;
// graph, status, name_map, and refiner.
// This is intended to enable the C API (which are used by other language
// bindings) to create a Scope and access C++ functionality (i.e. gradients).
+//
+// Shape inference is disabled if `refiner` is nullptr.
Scope NewInternalScope(Graph* graph, Status* status, ShapeRefiner* refiner);
class Scope::Impl {
@@ -58,6 +60,7 @@ class Scope::Impl {
enum class ExitOnError;
enum class KernelLabel;
enum class Colocate;
+ enum class AssignedDevice;
};
Impl(Graph* graph, Status* status, NameMap* name_map, ShapeRefiner* refiner,
@@ -74,6 +77,7 @@ class Scope::Impl {
Impl(const Scope& other, Tags::KernelLabel, const string& kernel_label);
Impl(const Scope& other, Tags::Colocate, const Operation& colocate_with_op,
bool clear_colocations);
+ Impl(const Scope& other, Tags::AssignedDevice, const string& assigned_device);
std::unordered_set GetColocationConstraints(
const Operation& colocate_with_op) const;
@@ -107,6 +111,7 @@ class Scope::Impl {
const bool exit_on_error_ = false;
const string kernel_label_ = "";
const string device_ = "";
+ const string assigned_device_ = "";
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