Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the codeobject pointer to idetify regions #105

Merged
merged 29 commits into from
Jul 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
df41342
a first approach
AndreasGocht Jun 12, 2020
35daf29
special case, using the object pointer
AndreasGocht Jun 12, 2020
17fec66
adopt testcase
AndreasGocht Jun 12, 2020
30f6965
working state
AndreasGocht Jun 24, 2020
f991814
Merge remote-tracking branch 'origin/master' into issue-88
AndreasGocht Jun 24, 2020
d92c5d6
working with code pointer on profile
AndreasGocht Jun 24, 2020
df09265
address user regions with line numbers#
AndreasGocht Jun 24, 2020
b9e4887
update tests
AndreasGocht Jun 24, 2020
ecb1fdd
only create name when needed
AndreasGocht Jun 24, 2020
882d8c2
fix region and module order
AndreasGocht Jun 24, 2020
c01aa1f
extend the other instrumenters
AndreasGocht Jun 24, 2020
ec407c9
update README.md
AndreasGocht Jun 24, 2020
a396c80
autopep8
AndreasGocht Jun 24, 2020
fa506c1
Apply suggestions from code review
AndreasGocht Jul 6, 2020
fbdcffa
sperate user regions and instrumented or decorated regions
AndreasGocht Jul 15, 2020
09ff745
fix style
AndreasGocht Jul 15, 2020
5eb191d
back to ref
AndreasGocht Jul 15, 2020
ac703fd
region --> function_name
AndreasGocht Jul 15, 2020
e2ac3e8
&SCOREP_User_LastFileHandle --> NULL
AndreasGocht Jul 15, 2020
3c708ab
Update scorep/user.py
AndreasGocht Jul 15, 2020
8afb236
Update src/scorepy/events.cpp
AndreasGocht Jul 15, 2020
6cafede
Update src/scorepy/events.cpp
AndreasGocht Jul 15, 2020
a609531
Update src/scorepy/events.hpp
AndreasGocht Jul 15, 2020
9274ba9
Update src/scorepy/events.cpp
AndreasGocht Jul 15, 2020
646767b
remove optional arguments
AndreasGocht Jul 15, 2020
4793e03
restructure code, to make things more clear.
AndreasGocht Jul 15, 2020
0996309
codestyle
AndreasGocht Jul 15, 2020
05a4fe9
some doc
AndreasGocht Jul 15, 2020
e7f01a9
Merge remote-tracking branch 'origin/master' into issue-88
AndreasGocht Jul 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ Please be aware the `--user` is always passed to Score-P, as this is needed for
## Not Working
* python multiprocessing
* Score-P does currently only support MPI or SHMEM. Any other multiprocessing approach cannot be traced.
* tracking `importlib.reload()`

# Acknowledgments
The European Union initially supported this work as part of the European Union’s Horizon 2020 project READEX (grant agreement number 671657).
4 changes: 2 additions & 2 deletions scorep/_instrumenters/base_instrumenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ def run(self, cmd, globals=None, locals=None):
pass

@abc.abstractmethod
def region_begin(self, module_name, function_name, file_name, line_number):
def region_begin(self, module_name, function_name, file_name, line_number, code_object):
pass

@abc.abstractmethod
def region_end(self, module_name, function_name):
def region_end(self, module_name, function_name, code_object):
pass

@abc.abstractmethod
Expand Down
4 changes: 2 additions & 2 deletions scorep/_instrumenters/dummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ def run(self, cmd, globals=None, locals=None):
locals = {}
exec(cmd, globals, locals)

def region_begin(self, module_name, function_name, file_name, line_number):
def region_begin(self, module_name, function_name, file_name, line_number, code_object=None):
pass

def region_end(self, module_name, function_name):
def region_end(self, module_name, function_name, code_object=None):
pass

def rewind_begin(self, name, file_name=None, line_number=None):
Expand Down
8 changes: 4 additions & 4 deletions scorep/_instrumenters/scorep_instrumenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ def run(self, cmd, globals=None, locals=None):
finally:
self.unregister()

def region_begin(self, module_name, function_name, file_name, line_number):
def region_begin(self, module_name, function_name, file_name, line_number, code_object=None):
"""Record a region begin event"""
scorep._bindings.region_begin(
module_name, function_name, file_name, line_number)
module_name, function_name, file_name, line_number, code_object)

def region_end(self, module_name, function_name):
def region_end(self, module_name, function_name, code_object=None):
"""Record a region end event"""
scorep._bindings.region_end(module_name, function_name)
scorep._bindings.region_end(module_name, function_name, code_object)

def rewind_begin(self, name, file_name=None, line_number=None):
"""
Expand Down
5 changes: 3 additions & 2 deletions scorep/_instrumenters/scorep_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@ def _globaltrace(self, frame, why, arg):
if why == 'call':
code = frame.f_code
modulename = get_module_name(frame)

if not code.co_name == "_unsetprofile" and not modulename[:6] == "scorep":
full_file_name = get_file_name(frame)
line_number = code.co_firstlineno
scorep._bindings.region_begin(modulename, code.co_name, full_file_name, line_number)
scorep._bindings.region_begin(modulename, code.co_name, full_file_name, line_number, code)
elif why == 'return':
code = frame.f_code
modulename = get_module_name(frame)
if not code.co_name == "_unsetprofile" and not modulename[:6] == "scorep":
scorep._bindings.region_end(modulename, code.co_name)
scorep._bindings.region_end(modulename, code.co_name, code)
4 changes: 2 additions & 2 deletions scorep/_instrumenters/scorep_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ def _globaltrace(self, frame, why, arg):
if not code.co_name == "_unsettrace" and not modulename[:6] == "scorep":
full_file_name = get_file_name(frame)
line_number = code.co_firstlineno
scorep._bindings.region_begin(modulename, code.co_name, full_file_name, line_number)
scorep._bindings.region_begin(modulename, code.co_name, full_file_name, line_number, code)
return self._localtrace
return None

def _localtrace(self, frame, why, arg):
if why == 'return':
code = frame.f_code
modulename = get_module_name(frame)
scorep._bindings.region_end(modulename, code.co_name)
scorep._bindings.region_end(modulename, code.co_name, code)
return self._localtrace
72 changes: 40 additions & 32 deletions scorep/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def __enter__(self):
initally_registered = scorep.instrumenter.get_instrumenter().get_registered()
with scorep.instrumenter.disable():
if(self.user_region_name):
# The user did specify a region name, so its a user_region
self.module_name = "user"
frame = inspect.currentframe().f_back
file_name = frame.f_globals.get('__file__', None)
Expand All @@ -85,46 +86,53 @@ def __enter__(self):

scorep.instrumenter.get_instrumenter().region_begin(
self.module_name, self.region_name, full_file_name, line_number)
elif(callable(self.func)):
"""
looks like the decorator is invoked
"""
if not initally_registered:
self.region_name = self.func.__name__
self.module_name = self.func.__module__
file_name = self.func.__code__.co_filename
line_number = self.func.__code__.co_firstlineno

if file_name is not None:
full_file_name = os.path.abspath(file_name)
else:
full_file_name = "None"

scorep.instrumenter.get_instrumenter().region_begin(
self.module_name, self.region_name, full_file_name, line_number)
elif callable(self.func) and not initally_registered:
# The user did not specify a region name, and it's a callable, so it's a semi instrumented region
self.region_name = self.func.__name__
self.module_name = self.func.__module__
self.code_obj = self.func.__code__
file_name = self.func.__code__.co_filename
line_number = self.func.__code__.co_firstlineno

if file_name is not None:
full_file_name = os.path.abspath(file_name)
else:
"""
do not need to decorate a function, when we are registerd. It is instrumented any way.
"""
pass
full_file_name = "None"

scorep.instrumenter.get_instrumenter().region_begin(
self.module_name, self.region_name, full_file_name, line_number, self.code_obj)
elif callable(self.func) and initally_registered:
# The user did not specify a region name, and it's a callable, so it's a
# semi instrumented region. However, the instrumenter is active, so there
# is nothing to do.
pass
else:
raise RuntimeError("a region name needs to be specified")
# The user did not specify a region name, and it's not a callable. So it
# is a context region without a region name. Throw an error.
raise RuntimeError("A region name needs to be specified.")

return self

def __exit__(self, exc_type, exc_value, traceback):
if (callable(self.func)
and scorep.instrumenter.get_instrumenter().get_registered()
and not self.user_region_name):
"""
looks like there is a decorator, we are registered and the name is not specified by the user,
so we do not need to do anything. The Instrumentation will take care.
"""
return False
else:
initally_registered = scorep.instrumenter.get_instrumenter().get_registered()
if self.user_region_name:
# The user did specify a region name, so its a user_region
scorep.instrumenter.get_instrumenter().region_end(
self.module_name, self.region_name)
return False
elif callable(self.func) and not initally_registered:
# The user did not specify a region name, and it's a callable, so it's a semi instrumented region
scorep.instrumenter.get_instrumenter().region_end(
self.module_name, self.region_name, self.code_obj)
elif callable(self.func) and initally_registered:
# The user did not specify a region name, and it's a callable, so it's a
# semi instrumented region. However, the instrumenter is active, so there
# is nothing to do.
pass
else:
# The user did not specify a region name, and it's not a callable. So it
# is a context region without a region name. Throw an error.
raise RuntimeError("Something wen't wrong. Please do a Bug Report.")
return False


def rewind_begin(name, file_name=None, line_number=None):
Expand Down
43 changes: 33 additions & 10 deletions src/methods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <cstdint>
#include <scorep/SCOREP_User_Functions.h>

#include <iostream>

extern "C"
{

Expand All @@ -28,15 +30,26 @@ extern "C"
static PyObject* region_begin(PyObject* self, PyObject* args)
{
const char* module;
const char* region_name;
const char* function_name;
const char* file_name;
PyObject* identifier = nullptr;
std::uint64_t line_number = 0;

if (!PyArg_ParseTuple(args, "sssK", &module, &region_name, &file_name, &line_number))
if (!PyArg_ParseTuple(args, "sssKO", &module, &function_name, &file_name, &line_number,
&identifier))
{
return NULL;

const std::string& region = scorepy::make_region_name(module, region_name);
scorepy::region_begin(region, module, file_name, line_number);
}

if (identifier == nullptr or identifier == Py_None)
{
scorepy::region_begin(function_name, module, file_name, line_number);
}
else
{
scorepy::region_begin(function_name, module, file_name, line_number,
reinterpret_cast<std::uintptr_t>(identifier));
}

Py_RETURN_NONE;
}
Expand All @@ -47,13 +60,23 @@ extern "C"
static PyObject* region_end(PyObject* self, PyObject* args)
{
const char* module;
const char* region_name;
const char* function_name;
PyObject* identifier = nullptr;

if (!PyArg_ParseTuple(args, "ss", &module, &region_name))
if (!PyArg_ParseTuple(args, "ssO", &module, &function_name, &identifier))
{
return NULL;

const std::string& region = scorepy::make_region_name(module, region_name);
scorepy::region_end(region);
}

if (identifier == nullptr or identifier == Py_None)
{
scorepy::region_end(function_name, module);
}
else
{
scorepy::region_end(function_name, module,
reinterpret_cast<std::uintptr_t>(identifier));
}

Py_RETURN_NONE;
}
Expand Down
8 changes: 4 additions & 4 deletions src/scorepy/cInstrumenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "pythonHelpers.hpp"
#include <algorithm>
#include <array>
#include <cstdint>
#include <string>

namespace scorepy
Expand Down Expand Up @@ -122,9 +123,9 @@ bool CInstrumenter::on_event(PyFrameObject& frame, int what, PyObject*)
if (std::string(name) != "_unsetprofile" && std::string(module_name, 0, 6) != "scorep")
{
const int line_number = code.co_firstlineno;
const auto& region_name = make_region_name(module_name, name);
const auto file_name = get_file_name(frame);
region_begin(region_name, module_name, file_name, line_number);
region_begin(name, module_name, file_name, line_number,
reinterpret_cast<std::uintptr_t>(&code));
}
break;
}
Expand All @@ -138,8 +139,7 @@ bool CInstrumenter::on_event(PyFrameObject& frame, int what, PyObject*)
// TODO: Use string_view/CString comparison?
if (std::string(name) != "_unsetprofile" && std::string(module_name, 0, 6) != "scorep")
{
const auto& region_name = make_region_name(module_name, name);
region_end(region_name);
region_end(name, module_name, reinterpret_cast<std::uintptr_t>(&code));
}
break;
}
Expand Down
Loading