Skip to content

Commit

Permalink
Merge pull request #1 from xldrx/monkey-patching
Browse files Browse the repository at this point in the history
Add Monkey Patching
  • Loading branch information
xldrx authored Nov 30, 2018
2 parents c115e86 + d7ae174 commit 0db65fe
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 7 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ pip install tensorflow-tracer
http://0.0.0.0:9999
```

## How to Trace an Existing Code

If you want to trace an existing script without any modification use `tftracer.hook_inject`
Please note that this is experimental and may cause unexpected errors:

1. Add the following to the beggining of the main script:
.. code-block:: python

import tftracer
tftracer.hook_inject()
...
2. Run your code and browse to `http://0.0.0.0:9999`


## Command line
Tracing sessions can be stored either through the web interface or by calling `tracing_server.save_session(filename)`.

Expand Down
5 changes: 3 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@

sys.path.insert(0, os.path.abspath('..'))

from tftracer.version import __version__
# -- Project information -----------------------------------------------------

project = 'TensorFlow Runtime Tracer'
copyright = '2018, Sayed Hadi Hashemi'
author = 'Sayed Hadi Hashemi'

# The short X.Y version
version = '1.0.2'
version = __version__
# The full version, including alpha/beta/rc tags
release = '1.0.2'
release = __version__


# -- General configuration ---------------------------------------------------
Expand Down
31 changes: 31 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,30 @@ How to Use

http://0.0.0.0:9999

How to Trace an Existing Code
=============================

If you want to trace an existing script without any modification use :func:`tftracer.hook_inject`. Please note that
this is experimental and may cause unexpected errors:

#.
Add the following to the beggining of the main script:

.. code-block:: python
import tftracer
tftracer.hook_inject()
...
#.
Run your code and browse to:

.. code-block:: html

http://0.0.0.0:9999


Command line
============

Expand Down Expand Up @@ -111,6 +135,9 @@ Examples
Low-Level API <`monitoredtrainingsession-example.py <https://github.com/xldrx/tensorflow-tracer/blob/master/examples/monitoredtrainingsession-example.py>`__>
Example of using :class:`tftracer.TracingServer` with TensorFlow ``MonitoredTrainingSession`` API.

Monkey Patching <`monkey_patching-example.py <https://github.com/xldrx/tensorflow-tracer/blob/master/examples/monkey_patching-example.py>`__>
Example of using :func:`tftracer.hook_inject` to trace a script without any modifications.

Horovod: One Process <`horovod-example.py <https://github.com/xldrx/tensorflow-tracer/blob/master/examples/horovod-example.py>`__>
Example of using :class:`tftracer.TracingServer` with ``horovod``. In this example only the one process is being traced.

Expand Down Expand Up @@ -145,6 +172,10 @@ tftracer.Timeline
:undoc-members:
:exclude-members: communication_elapsed_time, communication_time, computation_time

tftracer.hook_inject
--------------------
.. automodule:: tftracer
:members: hook_inject


Known Bugs/Limitations
Expand Down
5 changes: 5 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ Example of using `tftracer.TracingServer` with TensorFlow ``estimator`` API.
[monitoredtrainingsession-example.py](https://github.com/xldrx/tensorflow-tracer/blob/master/examples/monitoredtrainingsession-example.py)
<br/>
Example of using `tftracer.TracingServer` with TensorFlow `MonitoredTrainingSession` API.

### Monkey Patching
[monkey_patching-example.py](https://github.com/xldrx/tensorflow-tracer/blob/master/examples/monkey_patching-example.py)
<br/>
Example of using `tftracer.hook_inject` to trace a script without any modifications.

### Horovod: One Process
[horovod-example.py](https://github.com/xldrx/tensorflow-tracer/blob/master/examples/horovod-example.py)
Expand Down
46 changes: 46 additions & 0 deletions examples/monkey_patching-example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#! /usr/bin/env python -u
# coding=utf-8

# Using tracing server with TesorFlow Estimator API

__author__ = 'Sayed Hadi Hashemi'

import tensorflow as tf

import tftracer
tftracer.hook_inject()

import numpy as np

INPUT_SIZE = (299, 299, 3)
MINIBATCH_SIZE = 128
NUM_CLASSES = 1000
NUM_STEPS = 500


def input_fn():
dataset = tf.data.Dataset.from_tensor_slices([0]).repeat(MINIBATCH_SIZE)
dataset = dataset.map(
lambda _:
(
{"x": np.random.uniform(size=INPUT_SIZE)},
[np.random.random_integers(0, NUM_CLASSES)]
)
)
dataset = dataset.repeat(NUM_STEPS).batch(MINIBATCH_SIZE)
return dataset


def main():
estimator = tf.estimator.DNNClassifier(
hidden_units=[10] * 150,
feature_columns=[tf.feature_column.numeric_column("x", shape=INPUT_SIZE)],
n_classes=NUM_CLASSES,
)
estimator.train(input_fn)
estimator.evaluate(input_fn)


if __name__ == '__main__':
tf.logging.set_verbosity(tf.logging.INFO)
main()
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import setup
import os

from tftracer.version import __version__
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), "README.md"), "r") as fp:
long_description = fp.read()

Expand All @@ -10,7 +10,7 @@

setup(
name='tensorflow-tracer',
version='1.0.2',
version=__version__,
packages=['tftracer'],
url='https://github.com/xldrx/tensorflow-tracer',
license='Apache-2.0',
Expand Down
4 changes: 2 additions & 2 deletions tftracer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@

from .timeline import Timeline
from .tracing_server import TracingServer

__version__ = '1.0.2'
from .monkey_patching import hook_inject
from .version import __version__
72 changes: 72 additions & 0 deletions tftracer/monkey_patching.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#! /usr/bin/env python -u
# coding=utf-8

__author__ = 'Sayed Hadi Hashemi'


def __add_tracing_server_hook(hooks):
if hooks is None:
return [hook_inject.__tracing_server.hook]
else:
hooks = list(hooks)
hooks.append(hook_inject.__tracing_server.hook)
return hooks


def __new_init(*args, **kwargs):
if hook_inject.__original_init is None:
return

if "hooks" in hook_inject.__original_init.__code__.co_varnames:
hooks_index = hook_inject.__original_init.__code__.co_varnames.index("hooks")
if len(args) > hooks_index:
args = list(args)
args[hooks_index] = __add_tracing_server_hook(args[hooks_index])
else:
kwargs["hooks"] = __add_tracing_server_hook(kwargs.get("hooks", None))
else:
print("'hooks' not in '_MonitoredSession'")

hook_inject.__original_init(*args, **kwargs)


def hook_inject(*args, **kwargs):
"""
(Experimental) Injects a tracing server hook to all instances of ``MonitoredSession`` by by monkey patching
the initializer. This function is an alternative to adding `hooks` to estimator or sessions.
Be aware, monkey patching could cause unexpected errors and is not recommended.
This function should be called once in the main script preferably before importing anything else.
Example:
.. code-block:: python
import tftracer
tftracer.hook_inject()
...
estimator.train(input_fn)
Args:
**kwargs: same as :class:`tftracer.TracingServer`.
Note:
Monkey Patching (as :class:`tftracer.TracingServer`) works only with subclasses of ``MonitoredSession``.
For other ``Session`` types, use :class:`tftracer.Timeline`.
"""
from . import TracingServer
from tensorflow.python.training.monitored_session import _MonitoredSession

if hook_inject.__original_init is None:
hook_inject.__original_init = _MonitoredSession.__init__
hook_inject.__tracing_server = TracingServer(*args, **kwargs)
_MonitoredSession.__init__ = __new_init


hook_inject.__tracing_server = None
hook_inject.__original_init = None
3 changes: 2 additions & 1 deletion tftracer/tracing_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import threading
from .timeline import Timeline
import tensorflow as tf

from .version import __version__

class VisualizationServerBase:
def __init__(self, server_port=9999, server_ip="0.0.0.0", **kwargs):
Expand Down Expand Up @@ -170,6 +170,7 @@ def _get_flask_app(self):


class TracingSource:
tftracer_version = __version__

def __init__(self, **kwargs):
self._run_profile = OrderedDict()
Expand Down
6 changes: 6 additions & 0 deletions tftracer/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#! /usr/bin/env python -u
# coding=utf-8

__author__ = 'Sayed Hadi Hashemi'

__version__ = '1.1.0'

0 comments on commit 0db65fe

Please sign in to comment.