Speedup python TraceMe

PiperOrigin-RevId: 313271773
Change-Id: I6358253077190f43059fed416399852bab29dae6
This commit is contained in:
Jose Baiocchi 2020-05-26 14:48:04 -07:00 committed by TensorFlower Gardener
parent 13f50c2b7a
commit aff44e4ca1
6 changed files with 51 additions and 61 deletions

View File

@ -261,7 +261,7 @@ pybind_extension(
"//tensorflow/core/profiler/lib:profiler_backends", "//tensorflow/core/profiler/lib:profiler_backends",
"//tensorflow/core/profiler/lib:profiler_session", "//tensorflow/core/profiler/lib:profiler_session",
"//tensorflow/core/profiler/rpc:profiler_server", "//tensorflow/core/profiler/rpc:profiler_server",
"//tensorflow/python/profiler/internal:traceme_context_manager", "//tensorflow/python/profiler/internal:traceme_wrapper",
"//tensorflow/stream_executor:device_memory_allocator", "//tensorflow/stream_executor:device_memory_allocator",
"//tensorflow/stream_executor:platform", "//tensorflow/stream_executor:platform",
] + select({ ] + select({

View File

@ -64,7 +64,7 @@ limitations under the License.
#include "tensorflow/compiler/xla/xla_data.pb.h" #include "tensorflow/compiler/xla/xla_data.pb.h"
#include "tensorflow/core/platform/errors.h" #include "tensorflow/core/platform/errors.h"
#include "tensorflow/core/profiler/rpc/profiler_server.h" #include "tensorflow/core/profiler/rpc/profiler_server.h"
#include "tensorflow/python/profiler/internal/traceme_context_manager.h" #include "tensorflow/python/profiler/internal/traceme_wrapper.h"
#include "tensorflow/stream_executor/platform.h" #include "tensorflow/stream_executor/platform.h"
namespace xla { namespace xla {
@ -72,7 +72,7 @@ namespace {
namespace py = pybind11; namespace py = pybind11;
using ::tensorflow::profiler::TraceMeContextManager; using ::tensorflow::profiler::TraceMeWrapper;
struct Uniquer { struct Uniquer {
absl::Mutex mu; absl::Mutex mu;
@ -637,23 +637,19 @@ void BuildProfilerSubmodule(py::module* m) {
}, },
py::arg("port")); py::arg("port"));
py::class_<TraceMeContextManager> traceme_class(profiler, "TraceMe", py::class_<TraceMeWrapper> traceme_class(profiler, "TraceMe",
py::module_local()); py::module_local());
traceme_class.def(py::init<py::str, py::kwargs>()) traceme_class.def(py::init<py::str, py::kwargs>())
.def("__enter__", .def("__enter__", [](py::object self) -> py::object { return self; })
[](py::object self) -> py::object {
py::cast<TraceMeContextManager*>(self)->Enter();
return self;
})
.def("__exit__", .def("__exit__",
[](py::object self, const py::object& ex_type, [](py::object self, const py::object& ex_type,
const py::object& ex_value, const py::object& ex_value,
const py::object& traceback) -> py::object { const py::object& traceback) -> py::object {
py::cast<TraceMeContextManager*>(self)->Exit(); py::cast<TraceMeWrapper*>(self)->Stop();
return py::none(); return py::none();
}) })
.def("set_metadata", &TraceMeContextManager::SetMetadata) .def("set_metadata", &TraceMeWrapper::SetMetadata)
.def_static("is_enabled", &TraceMeContextManager::IsEnabled); .def_static("is_enabled", &TraceMeWrapper::IsEnabled);
} }
} // namespace } // namespace

View File

@ -86,14 +86,14 @@ tf_python_pybind_extension(
"//tensorflow/python/profiler:__subpackages__", "//tensorflow/python/profiler:__subpackages__",
], ],
deps = [ deps = [
":traceme_context_manager", ":traceme_wrapper",
"@pybind11", "@pybind11",
], ],
) )
cc_library( cc_library(
name = "traceme_context_manager", name = "traceme_wrapper",
hdrs = ["traceme_context_manager.h"], hdrs = ["traceme_wrapper.h"],
features = ["-layering_check"], features = ["-layering_check"],
visibility = [ visibility = [
"//tensorflow/compiler/xla/python:__pkg__", "//tensorflow/compiler/xla/python:__pkg__",

View File

@ -13,18 +13,18 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==============================================================================*/ ==============================================================================*/
#include "tensorflow/python/profiler/internal/traceme_wrapper.h"
#include "pybind11/attr.h" #include "pybind11/attr.h"
#include "pybind11/pybind11.h" #include "pybind11/pybind11.h"
#include "tensorflow/python/profiler/internal/traceme_context_manager.h"
using ::tensorflow::profiler::TraceMeContextManager; namespace py = ::pybind11;
using ::tensorflow::profiler::TraceMeWrapper;
PYBIND11_MODULE(_pywrap_traceme, m) { PYBIND11_MODULE(_pywrap_traceme, m) {
py::class_<TraceMeContextManager> traceme_class(m, "TraceMe", py::class_<TraceMeWrapper>(m, "TraceMe", py::module_local())
py::module_local()); .def(py::init<const py::str&, const py::kwargs&>())
traceme_class.def(py::init<py::str, py::kwargs>()) .def("SetMetadata", &TraceMeWrapper::SetMetadata)
.def("Enter", &TraceMeContextManager::Enter) .def_static("IsEnabled", &TraceMeWrapper::IsEnabled);
.def("Exit", &TraceMeContextManager::Exit)
.def("SetMetadata", &TraceMeContextManager::SetMetadata)
.def_static("IsEnabled", &TraceMeContextManager::IsEnabled);
}; };

View File

@ -12,46 +12,41 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==============================================================================*/ ==============================================================================*/
#ifndef TENSORFLOW_PYTHON_PROFILER_INTERNAL_TRACEME_CONTEXT_MANAGER_ #ifndef TENSORFLOW_PYTHON_PROFILER_INTERNAL_TRACEME_WRAPPER_
#define TENSORFLOW_PYTHON_PROFILER_INTERNAL_TRACEME_CONTEXT_MANAGER_ #define TENSORFLOW_PYTHON_PROFILER_INTERNAL_TRACEME_WRAPPER_
#include <string> #include <string>
#include <utility> #include <utility>
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "pybind11/pytypes.h" #include "pybind11/pytypes.h"
#include "tensorflow/core/platform/macros.h" #include "tensorflow/core/platform/macros.h"
#include "tensorflow/core/platform/types.h" #include "tensorflow/core/platform/types.h"
#include "tensorflow/core/profiler/lib/traceme.h" #include "tensorflow/core/profiler/lib/traceme.h"
namespace py = pybind11;
namespace tensorflow { namespace tensorflow {
namespace profiler { namespace profiler {
// Helper to implement TraceMe as a context manager in Python. // Wraps TraceMe with an interface that takes python types.
class TraceMeContextManager { class TraceMeWrapper {
public: public:
explicit TraceMeContextManager(py::str name, py::kwargs kwargs) // pybind11::str and pybind11::kwargs are taken by const reference to avoid
: name_(std::move(name)), kwargs_(std::move(kwargs)) {} // python reference-counting overhead.
TraceMeWrapper(const pybind11::str& name, const pybind11::kwargs& kwargs)
: traceme_([&]() {
std::string name_and_metadata(name);
if (!kwargs.empty()) {
AppendMetadata(&name_and_metadata, kwargs);
}
return name_and_metadata;
}) {}
void Enter() { // pybind11::kwargs is taken by const reference to avoid python
if (IsEnabled()) { // reference-counting overhead.
traceme_.emplace([this]() { void SetMetadata(const pybind11::kwargs& kwargs) {
std::string name(name_); if (TF_PREDICT_FALSE(!kwargs.empty())) {
if (!kwargs_.empty()) { traceme_.AppendMetadata([&]() {
AppendMetadata(&name, kwargs_);
}
return name;
});
}
}
void SetMetadata(py::kwargs kwargs) {
if (TF_PREDICT_TRUE(traceme_.has_value() && !kwargs.empty())) {
traceme_->AppendMetadata([&kwargs]() {
std::string metadata; std::string metadata;
AppendMetadata(&metadata, kwargs); AppendMetadata(&metadata, kwargs);
return metadata; return metadata;
@ -59,28 +54,27 @@ class TraceMeContextManager {
} }
} }
void Exit() { traceme_.reset(); } void Stop() { traceme_.Stop(); }
static bool IsEnabled() { return tensorflow::profiler::TraceMe::Active(); } static bool IsEnabled() { return tensorflow::profiler::TraceMe::Active(); }
private: private:
// Converts kwargs to strings and appends them to name encoded as TraceMe // Converts kwargs to strings and appends them to name encoded as TraceMe
// metadata. // metadata.
static void AppendMetadata(std::string* name, const py::kwargs& kwargs) { static void AppendMetadata(std::string* name,
const pybind11::kwargs& kwargs) {
name->push_back('#'); name->push_back('#');
for (const auto& kv : kwargs) { for (const auto& kv : kwargs) {
absl::StrAppend(name, std::string(py::str(kv.first)), "=", absl::StrAppend(name, std::string(pybind11::str(kv.first)), "=",
std::string(py::str(kv.second)), ","); std::string(pybind11::str(kv.second)), ",");
} }
name->back() = '#'; name->back() = '#';
} }
py::str name_; tensorflow::profiler::TraceMe traceme_;
py::kwargs kwargs_;
absl::optional<tensorflow::profiler::TraceMe> traceme_;
}; };
} // namespace profiler } // namespace profiler
} // namespace tensorflow } // namespace tensorflow
#endif // TENSORFLOW_PYTHON_PROFILER_INTERNAL_TRACEME_CONTEXT_MANAGER_ #endif // TENSORFLOW_PYTHON_PROFILER_INTERNAL_TRACEME_WRAPPER_

View File

@ -73,13 +73,13 @@ class Trace(object):
training step being traced. training step being traced.
""" """
if _pywrap_traceme.TraceMe.IsEnabled(): if _pywrap_traceme.TraceMe.IsEnabled():
# Creating _pywrap_traceme.TraceMe starts the clock.
self._traceme = _pywrap_traceme.TraceMe(name, **kwargs) self._traceme = _pywrap_traceme.TraceMe(name, **kwargs)
else: else:
self._traceme = None self._traceme = None
def __enter__(self): def __enter__(self):
if self._traceme: # Starting the TraceMe clock here would require an extra Python->C++ call.
self._traceme.Enter()
return self return self
def set_metadata(self, **kwargs): def set_metadata(self, **kwargs):
@ -117,5 +117,5 @@ class Trace(object):
self._traceme.SetMetadata(**kwargs) self._traceme.SetMetadata(**kwargs)
def __exit__(self, exc_type, exc_val, exc_tb): def __exit__(self, exc_type, exc_val, exc_tb):
if self._traceme: # Deallocating _pywrap_traceme.TraceMe stops the clock.
self._traceme.Exit() self._traceme = None