aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/compiler
diff options
context:
space:
mode:
authorGravatar Yunxing Dai <yunxing@google.com>2018-08-29 13:52:19 -0700
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2018-08-29 13:56:04 -0700
commit91c7cd5676624d8c364d7dc56bb50300bb9d210c (patch)
treed91ebb16034a7f0734978fcc825934d11526bb8f /tensorflow/compiler
parent065f9b833ffbb3b2f03d63febb186275674ba133 (diff)
New XLA API to launch a program.
1. Propose a new API with ability to do input/output. 2. Start to enable ABSL in TF's codebase. PiperOrigin-RevId: 210783617
Diffstat (limited to 'tensorflow/compiler')
-rw-r--r--tensorflow/compiler/xla/service/BUILD19
-rw-r--r--tensorflow/compiler/xla/service/executable.h42
-rw-r--r--tensorflow/compiler/xla/service/maybe_owning_device_memory.cc41
-rw-r--r--tensorflow/compiler/xla/service/maybe_owning_device_memory.h70
-rw-r--r--tensorflow/compiler/xla/service/shaped_buffer.h8
-rw-r--r--tensorflow/compiler/xla/shape_tree.h25
-rw-r--r--tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc4
7 files changed, 201 insertions, 8 deletions
diff --git a/tensorflow/compiler/xla/service/BUILD b/tensorflow/compiler/xla/service/BUILD
index 4a3290e9bc..f8e0ed440d 100644
--- a/tensorflow/compiler/xla/service/BUILD
+++ b/tensorflow/compiler/xla/service/BUILD
@@ -788,9 +788,11 @@ cc_library(
":hlo_execution_profile",
":hlo_graph_dumper",
":hlo_proto",
+ ":maybe_owning_device_memory",
":shaped_buffer",
":stream_pool",
"//tensorflow/compiler/xla:executable_run_options",
+ "//tensorflow/compiler/xla:shape_tree",
"//tensorflow/compiler/xla:status",
"//tensorflow/compiler/xla:status_macros",
"//tensorflow/compiler/xla:statusor",
@@ -803,6 +805,7 @@ cc_library(
"//tensorflow/stream_executor",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/strings:str_format",
+ "@com_google_absl//absl/types:variant",
],
)
@@ -2679,6 +2682,22 @@ cc_library(
"//tensorflow/compiler/xla:util",
"//tensorflow/core:lib",
"//tensorflow/core:stream_executor_no_cuda",
+ "@com_google_absl//absl/types:variant",
+ ],
+)
+
+cc_library(
+ name = "maybe_owning_device_memory",
+ srcs = [
+ "maybe_owning_device_memory.cc",
+ ],
+ hdrs = [
+ "maybe_owning_device_memory.h",
+ ],
+ deps = [
+ ":device_memory_allocator",
+ "@com_google_absl//absl/types:optional",
+ "@com_google_absl//absl/types:variant",
],
)
diff --git a/tensorflow/compiler/xla/service/executable.h b/tensorflow/compiler/xla/service/executable.h
index 98eaeee30a..6e055edc03 100644
--- a/tensorflow/compiler/xla/service/executable.h
+++ b/tensorflow/compiler/xla/service/executable.h
@@ -18,7 +18,9 @@ limitations under the License.
#include <memory>
#include <utility>
+#include <vector>
+#include "absl/types/variant.h"
#include "tensorflow/compiler/xla/legacy_flags/debug_options_flags.h"
#include "tensorflow/compiler/xla/service/computation_layout.h"
#include "tensorflow/compiler/xla/service/device_memory_allocator.h"
@@ -26,8 +28,11 @@ limitations under the License.
#include "tensorflow/compiler/xla/service/hlo_execution_profile.h"
#include "tensorflow/compiler/xla/service/hlo_graph_dumper.h"
#include "tensorflow/compiler/xla/service/hlo_module.h"
+#include "tensorflow/compiler/xla/service/maybe_owning_device_memory.h"
+#include "tensorflow/compiler/xla/service/owning_device_memory.h"
#include "tensorflow/compiler/xla/service/service_executable_run_options.h"
#include "tensorflow/compiler/xla/service/shaped_buffer.h"
+#include "tensorflow/compiler/xla/shape_tree.h"
#include "tensorflow/compiler/xla/statusor.h"
#include "tensorflow/compiler/xla/util.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"
@@ -38,6 +43,19 @@ limitations under the License.
namespace xla {
+// ExecutionOutput encapsulates the output buffers of a execution and the
+// leftover buffers to be released by the caller.
+struct ExecutionOutput {
+ ExecutionOutput(ScopedShapedBuffer result,
+ std::vector<OwningDeviceMemory> to_be_released)
+ : result(std::move(result)), to_be_released(std::move(to_be_released)) {}
+ ScopedShapedBuffer result;
+
+ // Leftover buffers for the caller to release. Elements in this list are
+ // donated input memory buffers that are not reused by XLA as outputs.
+ std::vector<OwningDeviceMemory> to_be_released;
+};
+
// A given platform's compiler will produce an Executable -- this is a uniform
// interface that is used for launching compiled programs across platforms.
class Executable {
@@ -72,6 +90,30 @@ class Executable {
const ServiceExecutableRunOptions* run_options,
tensorflow::gtl::ArraySlice<const ShapedBuffer*> arguments) = 0;
+ // Starts the given program executing on the given stream/executor.
+ //
+ // `arguments` are ShapeTree containing the input parameters. For each element
+ // in the shape tree, if the element holds the ownership of the memory, it is
+ // considered donated and XLA will potentially reuse it as output buffers. For
+ // all donated inputs, XLA is also responsible for freeing them.
+ //
+ // If an input is donated to XLA but is not reused as output, it is returned
+ // as an leftover buffer for the caller to release.
+ virtual StatusOr<ExecutionOutput> ExecuteOnStream(
+ const ServiceExecutableRunOptions* run_options,
+ std::vector<ShapeTree<xla::MaybeOwningDeviceMemory>> arguments,
+ HloExecutionProfile* hlo_execution_profile) {
+ return Unimplemented(
+ "MaybeOwningDeviceMemory version of overload is not implemented ");
+ }
+
+ virtual StatusOr<ExecutionOutput> ExecuteAsyncOnStream(
+ const ServiceExecutableRunOptions* run_options,
+ std::vector<ShapeTree<xla::MaybeOwningDeviceMemory>> arguments) {
+ return Unimplemented(
+ "MaybeOwningDeviceMemory version of overload is not implemented ");
+ }
+
// Same as ExecuteOnStream(), but runs this executable on multiple
// streams. arguments[i] contains the arguments to the execution on
// run_options[i]->stream() and the returned value is at index i of the
diff --git a/tensorflow/compiler/xla/service/maybe_owning_device_memory.cc b/tensorflow/compiler/xla/service/maybe_owning_device_memory.cc
new file mode 100644
index 0000000000..8269842426
--- /dev/null
+++ b/tensorflow/compiler/xla/service/maybe_owning_device_memory.cc
@@ -0,0 +1,41 @@
+/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#include "tensorflow/compiler/xla/service/maybe_owning_device_memory.h"
+#include "absl/types/variant.h"
+namespace xla {
+
+se::DeviceMemoryBase MaybeOwningDeviceMemory::AsDeviceMemoryBase() {
+ if (HasOwnership()) {
+ return absl::get<OwningDeviceMemory>(mem_).AsDeviceMemoryBase();
+ } else {
+ return absl::get<se::DeviceMemoryBase>(mem_);
+ }
+}
+
+bool MaybeOwningDeviceMemory::HasOwnership() const {
+ return absl::holds_alternative<OwningDeviceMemory>(mem_);
+}
+
+absl::optional<OwningDeviceMemory> MaybeOwningDeviceMemory::Release() {
+ if (!HasOwnership()) {
+ return {};
+ }
+ OwningDeviceMemory result = std::move(absl::get<OwningDeviceMemory>(mem_));
+ mem_ = result.AsDeviceMemoryBase();
+ return absl::make_optional<OwningDeviceMemory>(std::move(result));
+}
+
+} // namespace xla
diff --git a/tensorflow/compiler/xla/service/maybe_owning_device_memory.h b/tensorflow/compiler/xla/service/maybe_owning_device_memory.h
new file mode 100644
index 0000000000..82e7f1183c
--- /dev/null
+++ b/tensorflow/compiler/xla/service/maybe_owning_device_memory.h
@@ -0,0 +1,70 @@
+/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#ifndef TENSORFLOW_COMPILER_XLA_SERVICE_MAYBE_OWNING_DEVICE_MEMORY_H_
+#define TENSORFLOW_COMPILER_XLA_SERVICE_MAYBE_OWNING_DEVICE_MEMORY_H_
+
+#include "absl/types/optional.h"
+#include "absl/types/variant.h"
+#include "tensorflow/compiler/xla/service/device_memory_allocator.h"
+#include "tensorflow/compiler/xla/service/owning_device_memory.h"
+
+namespace xla {
+
+// MaybeOwningDeviceMemory represents either an owned or unowned device memory.
+// Like std::variant<OwningDeviceMemory, DeviceMemory>. When the object goes
+// output of scope, it will free the underlying memory if it owns it.
+class MaybeOwningDeviceMemory {
+ public:
+ MaybeOwningDeviceMemory() = default;
+ explicit MaybeOwningDeviceMemory(OwningDeviceMemory owned)
+ : mem_(std::move(owned)) {}
+ explicit MaybeOwningDeviceMemory(se::DeviceMemoryBase unowned)
+ : mem_(unowned) {}
+ MaybeOwningDeviceMemory(MaybeOwningDeviceMemory&&) = default;
+ ~MaybeOwningDeviceMemory() = default;
+
+ MaybeOwningDeviceMemory& operator=(se::DeviceMemoryBase unowned) {
+ mem_ = unowned;
+ return *this;
+ }
+
+ MaybeOwningDeviceMemory& operator=(OwningDeviceMemory owned) {
+ mem_ = std::move(owned);
+ return *this;
+ }
+
+ MaybeOwningDeviceMemory& operator=(MaybeOwningDeviceMemory&&) = default;
+
+ // Fetches the underlying DeviceMemoryBase from a MaybeOwningDeviceMemory. The
+ // caller of this function is *not* responsible for freeing the memory.
+ se::DeviceMemoryBase AsDeviceMemoryBase();
+
+ // Release the OwningDeviceMemory without freeing it, and moves the ownership
+ // of the memory buffer from the object to the caller.
+ //
+ // A nullopt is returned if the HasOwnership() == false;
+ absl::optional<OwningDeviceMemory> Release();
+
+ // Returns true if the device_memory has ownership over underlying memory.
+ bool HasOwnership() const;
+
+ private:
+ absl::variant<OwningDeviceMemory, se::DeviceMemoryBase> mem_;
+};
+
+} // namespace xla
+
+#endif // TENSORFLOW_COMPILER_XLA_SERVICE_MAYBE_OWNING_DEVICE_MEMORY_H_
diff --git a/tensorflow/compiler/xla/service/shaped_buffer.h b/tensorflow/compiler/xla/service/shaped_buffer.h
index 905a7e82e6..05bde7bd98 100644
--- a/tensorflow/compiler/xla/service/shaped_buffer.h
+++ b/tensorflow/compiler/xla/service/shaped_buffer.h
@@ -84,6 +84,14 @@ class ShapedBuffer {
*buffers_.mutable_element(index) = buffer;
}
+ // Sets all buffers.
+ //
+ // Precondition: buffers.shape == on_device_shape_
+ void set_buffers(ShapeTree<se::DeviceMemoryBase> buffers) {
+ CHECK(ShapeUtil::Equal(buffers.shape(), on_device_shape_));
+ buffers_ = std::move(buffers);
+ }
+
// Returns the underlying ShapeTree containing all the device addresses in the
// ShapedBuffer.
const ShapeTree<se::DeviceMemoryBase>& buffers() const { return buffers_; }
diff --git a/tensorflow/compiler/xla/shape_tree.h b/tensorflow/compiler/xla/shape_tree.h
index c793a39c27..0c7df6468b 100644
--- a/tensorflow/compiler/xla/shape_tree.h
+++ b/tensorflow/compiler/xla/shape_tree.h
@@ -262,6 +262,25 @@ class ShapeTree {
template <typename Fn>
Status ForEachMutableElementWithStatus(const Fn& func);
+ // Maps each element to generate a new tree with the same shape.
+ template <typename U>
+ ShapeTree<U> Map(const std::function<U(const T&)>& func) {
+ ShapeTree<U> result(shape_storage_);
+ ForEachElement([&](const ShapeIndex& index, const T& t) {
+ *result.mutable_element(index) = func(t);
+ });
+ return result;
+ }
+
+ template <typename U>
+ ShapeTree<U> Map(const std::function<U(T*)>& func) {
+ ShapeTree<U> result(shape_storage_);
+ ForEachMutableElement([&](const ShapeIndex& index, T* t) {
+ *result.mutable_element(index) = func(t);
+ });
+ return result;
+ }
+
// Copy the subtree of values from 'other' rooted at ShapeIndex
// 'source_base_index' into the subtree of value in this ShapeTree rooted at
// 'target_base_index'.
@@ -463,9 +482,6 @@ template <typename T>
ShapeTree<T>::ShapeTree(Shape shape)
: shape_storage_(std::make_shared<Shape>(std::move(shape))),
shape_(shape_storage_.get()) {
- // The shape_ field is just used to hold the structure of the shape.
- // It should not be relied upon to store layout information.
- LayoutUtil::ClearLayout(shape_storage_.get());
const int64 count = CountSubshapes(*shape_);
nodes_.reserve(count);
nodes_.emplace_back(ShapeIndex{});
@@ -502,9 +518,6 @@ template <typename T>
ShapeTree<T>::ShapeTree(Shape shape, const T& init_value)
: shape_storage_(std::make_shared<Shape>(std::move(shape))),
shape_(shape_storage_.get()) {
- // The shape_ field is just used to hold the structure of the shape.
- // It should not be relied upon to store layout information.
- LayoutUtil::ClearLayout(shape_storage_.get());
const int64 count = CountSubshapes(*shape_);
nodes_.reserve(count);
nodes_.emplace_back(ShapeIndex{}, init_value);
diff --git a/tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc b/tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc
index 6a7ddd9b55..e3a0625780 100644
--- a/tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc
+++ b/tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc
@@ -171,10 +171,10 @@ void ExecuteAndFetchProfile(string* profile_output, LocalClient* client,
ServiceExecutableRunOptions run_options(
exec_run_options, /*borrow_stream=*/nullptr,
backend->eigen_intra_op_thread_pool());
+ std::vector<const ShapedBuffer*> args = {&lhs_arg, &rhs_arg};
TF_ASSERT_OK_AND_ASSIGN(
auto execution_result,
- executable->ExecuteOnStream(&run_options, {&lhs_arg, &rhs_arg},
- &hlo_execution_profile));
+ executable->ExecuteOnStream(&run_options, args, &hlo_execution_profile));
TF_ASSERT_OK(stream_ptr->BlockHostUntilDone());
(void)execution_result;