Skip to content

Commit 4dd144a

Browse files
authored
User regions in Python (#57)
* 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
1 parent 74fe681 commit 4dd144a

File tree

9 files changed

+371
-167
lines changed

9 files changed

+371
-167
lines changed

examples/python/source.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import os
44
import sys
5+
import time
56
import omnitrace
7+
from omnitrace.user import region as omni_user_region
68

79
_prefix = ""
810

@@ -60,10 +62,20 @@ def run(n):
6062
parser = argparse.ArgumentParser()
6163
parser.add_argument("-n", "--num-iterations", help="Number", type=int, default=3)
6264
parser.add_argument("-v", "--value", help="Starting value", type=int, default=20)
65+
parser.add_argument(
66+
"-s",
67+
"--stop-profile",
68+
help="Stop tracing after given iterations",
69+
type=int,
70+
default=0,
71+
)
6372
args = parser.parse_args()
6473

6574
_prefix = os.path.basename(__file__)
6675
print(f"[{_prefix}] Executing {args.num_iterations} iterations...\n")
6776
for i in range(args.num_iterations):
68-
ans = run(args.value)
69-
print(f"[{_prefix}] [{i}] result of run({args.value}) = {ans}\n")
77+
with omni_user_region(f"main_loop"):
78+
if args.stop_profile > 0 and i == args.stop_profile:
79+
omnitrace.user.stop_trace()
80+
ans = run(args.value)
81+
print(f"[{_prefix}] [{i}] result of run({args.value}) = {ans}\n")

source/python/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ target_link_libraries(
8888
omnitrace::omnitrace-compile-options
8989
omnitrace::omnitrace-lto
9090
omnitrace::omnitrace-dl-library
91+
omnitrace::omnitrace-user-library
9192
omnitrace::omnitrace-python
9293
omnitrace::omnitrace-python-compile-options
9394
$<BUILD_INTERFACE:$<IF:$<BOOL:${OMNITRACE_BUILD_STATIC_LIBGCC}>,omnitrace::omnitrace-static-libgcc,>>

source/python/libpyomnitrace.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "dl.hpp"
2525
#include "library/coverage.hpp"
2626
#include "library/impl/coverage.hpp"
27+
#include "omnitrace/user.h"
2728

2829
#include <timemory/backends/process.hpp>
2930
#include <timemory/backends/threading.hpp>
@@ -62,6 +63,11 @@ namespace pycoverage
6263
py::module
6364
generate(py::module& _pymod);
6465
}
66+
namespace pyuser
67+
{
68+
py::module
69+
generate(py::module& _pymod);
70+
}
6571
} // namespace pyomnitrace
6672

6773
template <typename... Tp>
@@ -158,8 +164,8 @@ PYBIND11_MODULE(libpyomnitrace, omni)
158164

159165
py::doc("omnitrace profiler for python");
160166
pyprofile::generate(omni);
161-
162167
pycoverage::generate(omni);
168+
pyuser::generate(omni);
163169
}
164170

165171
//======================================================================================//
@@ -824,6 +830,33 @@ generate(py::module& _pymod)
824830
return _pycov;
825831
}
826832
} // namespace pycoverage
833+
834+
namespace pyuser
835+
{
836+
py::module
837+
generate(py::module& _pymod)
838+
{
839+
py::module _pyuser = _pymod.def_submodule("user", "User instrumentation");
840+
841+
_pyuser.def("start_trace", &omnitrace_user_start_trace,
842+
"Enable tracing on this thread and all subsequently created threads");
843+
_pyuser.def("stop_trace", &omnitrace_user_stop_trace,
844+
"Disable tracing on this thread and all subsequently created threads");
845+
_pyuser.def(
846+
"start_thread_trace", &omnitrace_user_start_thread_trace,
847+
"Enable tracing on this thread. Does not apply to subsequently created threads");
848+
_pyuser.def(
849+
"stop_thread_trace", &omnitrace_user_stop_thread_trace,
850+
"Enable tracing on this thread. Does not apply to subsequently created threads");
851+
_pyuser.def("push_region", &omnitrace_user_push_region,
852+
"Start a user-defined region");
853+
_pyuser.def("pop_region", &omnitrace_user_pop_region, "Start a user-defined region");
854+
_pyuser.def("error_string", &omnitrace_user_error_string,
855+
"Return a descriptor for the provided error code");
856+
857+
return _pyuser;
858+
}
859+
} // namespace pyuser
827860
} // namespace pyomnitrace
828861
//
829862
//======================================================================================//

source/python/omnitrace/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
try:
3838
from .libpyomnitrace import coverage
39+
from . import user
3940
from .profiler import Profiler, FakeProfiler
4041
from .libpyomnitrace.profiler import (
4142
profiler_function,
@@ -67,6 +68,7 @@
6768
"profile",
6869
"noprofile",
6970
"coverage",
71+
"user",
7072
]
7173

7274
import atexit

source/python/omnitrace/common.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#!/usr/bin/env python@_VERSION@
2+
# MIT License
3+
#
4+
# Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
5+
#
6+
# Permission is hereby granted, free of charge, to any person obtaining a copy
7+
# of this software and associated documentation files (the "Software"), to deal
8+
# in the Software without restriction, including without limitation the rights
9+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
# copies of the Software, and to permit persons to whom the Software is
11+
# furnished to do so, subject to the following conditions:
12+
#
13+
# The above copyright notice and this permission notice shall be included in all
14+
# copies or substantial portions of the Software.
15+
#
16+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
# SOFTWARE.
23+
24+
from __future__ import absolute_import
25+
26+
__author__ = "AMD Research"
27+
__copyright__ = "Copyright 2022, Advanced Micro Devices, Inc."
28+
__license__ = "MIT"
29+
__version__ = "@PROJECT_VERSION@"
30+
__maintainer__ = "AMD Research"
31+
__status__ = "Development"
32+
33+
import os
34+
import sys
35+
36+
from . import libpyomnitrace
37+
from .libpyomnitrace.profiler import profiler_init as _profiler_init
38+
from .libpyomnitrace.profiler import profiler_finalize as _profiler_fini
39+
40+
41+
__all__ = ["exec_", "_file", "_get_argv", "_initialize", "_finalize"]
42+
43+
44+
PY3 = sys.version_info[0] == 3
45+
46+
# exec (from https://bitbucket.org/gutworth/six/):
47+
if PY3:
48+
import builtins
49+
50+
exec_ = getattr(builtins, "exec")
51+
del builtins
52+
else:
53+
54+
def exec_(_code_, _globs_=None, _locs_=None):
55+
"""Execute code in a namespace."""
56+
if _globs_ is None:
57+
frame = sys._getframe(1)
58+
_globs_ = frame.f_globals
59+
if _locs_ is None:
60+
_locs_ = frame.f_locals
61+
del frame
62+
elif _locs_ is None:
63+
_locs_ = _globs_
64+
exec("""exec _code_ in _globs_, _locs_""")
65+
66+
67+
def _file(back=2, only_basename=True, use_dirname=False, noquotes=True):
68+
"""
69+
Returns the file name
70+
"""
71+
72+
from os.path import basename, dirname
73+
74+
def get_fcode(back):
75+
fname = "<module>"
76+
try:
77+
fname = sys._getframe(back).f_code.co_filename
78+
except Exception as e:
79+
print(e)
80+
fname = "<module>"
81+
return fname
82+
83+
result = None
84+
if only_basename is True:
85+
if use_dirname is True:
86+
result = "{}".format(
87+
join(
88+
basename(dirname(get_fcode(back))),
89+
basename(get_fcode(back)),
90+
)
91+
)
92+
else:
93+
result = "{}".format(basename(get_fcode(back)))
94+
else:
95+
result = "{}".format(get_fcode(back))
96+
97+
if noquotes is False:
98+
result = "'{}'".format(result)
99+
100+
return result
101+
102+
103+
def _get_argv(init_file, argv=None):
104+
if argv is None:
105+
argv = sys.argv[:]
106+
107+
if "--" in argv:
108+
_idx = argv.index("--")
109+
argv = sys.argv[(_idx + 1) :]
110+
111+
if len(argv) > 1:
112+
if argv[0] == "-m":
113+
argv = argv[1:]
114+
elif argv[0] == "-c":
115+
argv[0] = os.path.basename(sys.executable)
116+
else:
117+
while len(argv) > 1 and argv[0].startswith("-"):
118+
argv = argv[1:]
119+
if os.path.exists(argv[0]):
120+
break
121+
if len(argv) == 0:
122+
argv = [init_file]
123+
elif not os.path.exists(argv[0]):
124+
argv[0] = init_file
125+
126+
return argv
127+
128+
129+
def _initialize(_file):
130+
if not libpyomnitrace.is_initialized():
131+
libpyomnitrace.initialize(_get_argv(_file))
132+
133+
134+
def _finalize():
135+
if libpyomnitrace.is_initialized() and not libpyomnitrace.is_finalized():
136+
_profiler_fini()

0 commit comments

Comments
 (0)