Skip to content

Commit

Permalink
User regions in Python (#57)
Browse files Browse the repository at this point in the history
* User regions in Python

* User-region testing + common submodule

- Updated examples/python/source.py to use user-regions
- Python-level user submodule
- Python-level common submodule
- clean-up of profiler python code
- extended source.py testing to include the user-regions
  • Loading branch information
jrmadsen authored Jul 26, 2022
1 parent 74fe681 commit 4dd144a
Show file tree
Hide file tree
Showing 9 changed files with 371 additions and 167 deletions.
16 changes: 14 additions & 2 deletions examples/python/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import os
import sys
import time
import omnitrace
from omnitrace.user import region as omni_user_region

_prefix = ""

Expand Down Expand Up @@ -60,10 +62,20 @@ def run(n):
parser = argparse.ArgumentParser()
parser.add_argument("-n", "--num-iterations", help="Number", type=int, default=3)
parser.add_argument("-v", "--value", help="Starting value", type=int, default=20)
parser.add_argument(
"-s",
"--stop-profile",
help="Stop tracing after given iterations",
type=int,
default=0,
)
args = parser.parse_args()

_prefix = os.path.basename(__file__)
print(f"[{_prefix}] Executing {args.num_iterations} iterations...\n")
for i in range(args.num_iterations):
ans = run(args.value)
print(f"[{_prefix}] [{i}] result of run({args.value}) = {ans}\n")
with omni_user_region(f"main_loop"):
if args.stop_profile > 0 and i == args.stop_profile:
omnitrace.user.stop_trace()
ans = run(args.value)
print(f"[{_prefix}] [{i}] result of run({args.value}) = {ans}\n")
1 change: 1 addition & 0 deletions source/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ target_link_libraries(
omnitrace::omnitrace-compile-options
omnitrace::omnitrace-lto
omnitrace::omnitrace-dl-library
omnitrace::omnitrace-user-library
omnitrace::omnitrace-python
omnitrace::omnitrace-python-compile-options
$<BUILD_INTERFACE:$<IF:$<BOOL:${OMNITRACE_BUILD_STATIC_LIBGCC}>,omnitrace::omnitrace-static-libgcc,>>
Expand Down
35 changes: 34 additions & 1 deletion source/python/libpyomnitrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "dl.hpp"
#include "library/coverage.hpp"
#include "library/impl/coverage.hpp"
#include "omnitrace/user.h"

#include <timemory/backends/process.hpp>
#include <timemory/backends/threading.hpp>
Expand Down Expand Up @@ -62,6 +63,11 @@ namespace pycoverage
py::module
generate(py::module& _pymod);
}
namespace pyuser
{
py::module
generate(py::module& _pymod);
}
} // namespace pyomnitrace

template <typename... Tp>
Expand Down Expand Up @@ -158,8 +164,8 @@ PYBIND11_MODULE(libpyomnitrace, omni)

py::doc("omnitrace profiler for python");
pyprofile::generate(omni);

pycoverage::generate(omni);
pyuser::generate(omni);
}

//======================================================================================//
Expand Down Expand Up @@ -824,6 +830,33 @@ generate(py::module& _pymod)
return _pycov;
}
} // namespace pycoverage

namespace pyuser
{
py::module
generate(py::module& _pymod)
{
py::module _pyuser = _pymod.def_submodule("user", "User instrumentation");

_pyuser.def("start_trace", &omnitrace_user_start_trace,
"Enable tracing on this thread and all subsequently created threads");
_pyuser.def("stop_trace", &omnitrace_user_stop_trace,
"Disable tracing on this thread and all subsequently created threads");
_pyuser.def(
"start_thread_trace", &omnitrace_user_start_thread_trace,
"Enable tracing on this thread. Does not apply to subsequently created threads");
_pyuser.def(
"stop_thread_trace", &omnitrace_user_stop_thread_trace,
"Enable tracing on this thread. Does not apply to subsequently created threads");
_pyuser.def("push_region", &omnitrace_user_push_region,
"Start a user-defined region");
_pyuser.def("pop_region", &omnitrace_user_pop_region, "Start a user-defined region");
_pyuser.def("error_string", &omnitrace_user_error_string,
"Return a descriptor for the provided error code");

return _pyuser;
}
} // namespace pyuser
} // namespace pyomnitrace
//
//======================================================================================//
2 changes: 2 additions & 0 deletions source/python/omnitrace/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

try:
from .libpyomnitrace import coverage
from . import user
from .profiler import Profiler, FakeProfiler
from .libpyomnitrace.profiler import (
profiler_function,
Expand Down Expand Up @@ -67,6 +68,7 @@
"profile",
"noprofile",
"coverage",
"user",
]

import atexit
Expand Down
136 changes: 136 additions & 0 deletions source/python/omnitrace/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#!/usr/bin/env python@_VERSION@
# MIT License
#
# Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from __future__ import absolute_import

__author__ = "AMD Research"
__copyright__ = "Copyright 2022, Advanced Micro Devices, Inc."
__license__ = "MIT"
__version__ = "@PROJECT_VERSION@"
__maintainer__ = "AMD Research"
__status__ = "Development"

import os
import sys

from . import libpyomnitrace
from .libpyomnitrace.profiler import profiler_init as _profiler_init
from .libpyomnitrace.profiler import profiler_finalize as _profiler_fini


__all__ = ["exec_", "_file", "_get_argv", "_initialize", "_finalize"]


PY3 = sys.version_info[0] == 3

# exec (from https://bitbucket.org/gutworth/six/):
if PY3:
import builtins

exec_ = getattr(builtins, "exec")
del builtins
else:

def exec_(_code_, _globs_=None, _locs_=None):
"""Execute code in a namespace."""
if _globs_ is None:
frame = sys._getframe(1)
_globs_ = frame.f_globals
if _locs_ is None:
_locs_ = frame.f_locals
del frame
elif _locs_ is None:
_locs_ = _globs_
exec("""exec _code_ in _globs_, _locs_""")


def _file(back=2, only_basename=True, use_dirname=False, noquotes=True):
"""
Returns the file name
"""

from os.path import basename, dirname

def get_fcode(back):
fname = "<module>"
try:
fname = sys._getframe(back).f_code.co_filename
except Exception as e:
print(e)
fname = "<module>"
return fname

result = None
if only_basename is True:
if use_dirname is True:
result = "{}".format(
join(
basename(dirname(get_fcode(back))),
basename(get_fcode(back)),
)
)
else:
result = "{}".format(basename(get_fcode(back)))
else:
result = "{}".format(get_fcode(back))

if noquotes is False:
result = "'{}'".format(result)

return result


def _get_argv(init_file, argv=None):
if argv is None:
argv = sys.argv[:]

if "--" in argv:
_idx = argv.index("--")
argv = sys.argv[(_idx + 1) :]

if len(argv) > 1:
if argv[0] == "-m":
argv = argv[1:]
elif argv[0] == "-c":
argv[0] = os.path.basename(sys.executable)
else:
while len(argv) > 1 and argv[0].startswith("-"):
argv = argv[1:]
if os.path.exists(argv[0]):
break
if len(argv) == 0:
argv = [init_file]
elif not os.path.exists(argv[0]):
argv[0] = init_file

return argv


def _initialize(_file):
if not libpyomnitrace.is_initialized():
libpyomnitrace.initialize(_get_argv(_file))


def _finalize():
if libpyomnitrace.is_initialized() and not libpyomnitrace.is_finalized():
_profiler_fini()
Loading

0 comments on commit 4dd144a

Please sign in to comment.