diff --git a/tensorflow/compiler/xla/service/cpu/cpu_executable.cc b/tensorflow/compiler/xla/service/cpu/cpu_executable.cc index e0c8adcbbe1..4552d7b5ba9 100644 --- a/tensorflow/compiler/xla/service/cpu/cpu_executable.cc +++ b/tensorflow/compiler/xla/service/cpu/cpu_executable.cc @@ -350,16 +350,7 @@ StatusOr CpuExecutable::ExecuteAsyncOnStream( std::move(buffers)), hlo_execution_profile}); - // TODO(cheshire): Duplication with other executables. - for (ExecutionInput& argument : arguments) { - for (auto& index_buffer : *argument.MutableBuffers()) { - absl::optional maybe_owning_buffer = - index_buffer.second.Release(); - if (maybe_owning_buffer) { - result.AddToBeReleased(std::move(*maybe_owning_buffer)); - } - } - } + MarkToBeReleasedArguments(absl::MakeSpan(arguments), result); return std::move(result); } diff --git a/tensorflow/compiler/xla/service/executable.cc b/tensorflow/compiler/xla/service/executable.cc index 4f210442005..ebf7cc440dd 100644 --- a/tensorflow/compiler/xla/service/executable.cc +++ b/tensorflow/compiler/xla/service/executable.cc @@ -258,4 +258,16 @@ StatusOr Executable::ExecuteAsyncOnStreamWrapper( int64 Executable::SizeOfGeneratedCodeInBytes() const { return -1; } +void Executable::MarkToBeReleasedArguments(absl::Span arguments, + ExecutionOutput& result) { + for (ExecutionInput& argument : arguments) { + for (auto& index_buffer : *argument.MutableBuffers()) { + if (absl::optional maybe_owning_buffer = + index_buffer.second.Release()) { + result.AddToBeReleased(std::move(*maybe_owning_buffer)); + } + } + } +} + } // namespace xla diff --git a/tensorflow/compiler/xla/service/executable.h b/tensorflow/compiler/xla/service/executable.h index 49614c1af00..2c979662d24 100644 --- a/tensorflow/compiler/xla/service/executable.h +++ b/tensorflow/compiler/xla/service/executable.h @@ -331,6 +331,15 @@ class Executable { bool dumping_snapshot() const { return hlo_proto_ != nullptr; } HloProto const* hlo_proto() const { return hlo_proto_.get(); } + // Gather unused but donated buffers, return them to the caller of this API. + // We don't free buffers inside this function since the caller could have + // different preferences for buffer deallocation. For example, in TensorFlow, + // buffers are mostly efficiently deallocated as soon as a program has been + // launched. However, in XRT, the buffers are expected to be deallocated after + // the program has finished since XRT doesn't support async deallocation. + void MarkToBeReleasedArguments(absl::Span arguments, + ExecutionOutput& result); + protected: // HloModule this was compiled from. BufferAssignment keeps pointers to // HloInstructions owned by the HloModule so we need to keep the HloModule diff --git a/tensorflow/compiler/xla/service/gpu/gpu_executable.cc b/tensorflow/compiler/xla/service/gpu/gpu_executable.cc index c8b11cab31a..520bbedbaeb 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_executable.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_executable.cc @@ -541,15 +541,7 @@ StatusOr GpuExecutable::ExecuteAsyncOnStream( buffer_allocations.TearDown(buffers_in_result, assignment_.get())); // Free allocations for arguments. - for (ExecutionInput& argument : arguments) { - for (auto& index_buffer : *argument.MutableBuffers()) { - if (absl::optional owning = - index_buffer.second.Release()) { - result.AddToBeReleased(std::move(*owning)); - } - } - } - + MarkToBeReleasedArguments(absl::MakeSpan(arguments), result); return std::move(result); } diff --git a/tensorflow/compiler/xla/service/interpreter/executable_base.cc b/tensorflow/compiler/xla/service/interpreter/executable_base.cc index 5850cbf005b..4b020ea2d32 100644 --- a/tensorflow/compiler/xla/service/interpreter/executable_base.cc +++ b/tensorflow/compiler/xla/service/interpreter/executable_base.cc @@ -122,14 +122,7 @@ StatusOr InterpreterExecutableBase::ExecuteAsyncOnStream( const double nanoseconds = (end_micros - start_micros) * 1000.0; profile->set_compute_time_ns(std::max(nanoseconds, 1.0)); } - for (auto& argument : arguments) { - for (auto& index_buffer : *argument.MutableBuffers()) { - auto maybe_owning_buffer = index_buffer.second.Release(); - if (maybe_owning_buffer) { - result.AddToBeReleased(std::move(*maybe_owning_buffer)); - } - } - } + MarkToBeReleasedArguments(absl::MakeSpan(arguments), result); return std::move(result); }