Skip to content

Commit 532373d

Browse files
authored
Merge pull request #92 from Flamefire/cTracing
Implement CInstrumenter
2 parents 9b05409 + 2bd18f7 commit 532373d

22 files changed

Lines changed: 684 additions & 52 deletions

CMakeLists.txt

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,22 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
1010
find_package(Scorep REQUIRED)
1111
find_package(Python REQUIRED COMPONENTS Interpreter Development)
1212

13-
Python_add_library(scorep_bindings
13+
Python_add_library(_bindings
1414
src/methods.cpp src/scorep_bindings.cpp src/scorepy/events.cpp
1515
)
16-
target_link_libraries(scorep_bindings PRIVATE Scorep::Plugin)
17-
target_compile_features(scorep_bindings PRIVATE cxx_std_11)
18-
target_compile_definitions(scorep_bindings PRIVATE PY_SSIZE_T_CLEAN)
19-
target_include_directories(scorep_bindings PRIVATE src)
16+
if(Python_VERSION_MAJOR GREATER_EQUAL 3)
17+
target_sources(_bindings PRIVATE src/classes.cpp src/scorepy/cInstrumenter.cpp src/scorepy/pythonHelpers.cpp)
18+
endif()
19+
target_link_libraries(_bindings PRIVATE Scorep::Plugin)
20+
target_compile_features(_bindings PRIVATE cxx_std_11)
21+
target_compile_definitions(_bindings PRIVATE PY_SSIZE_T_CLEAN)
22+
target_include_directories(_bindings PRIVATE src)
2023

21-
set_target_properties(scorep_bindings PROPERTIES
24+
set_target_properties(_bindings PROPERTIES
2225
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/site-packages/scorep
2326
)
2427
add_custom_target(ScorepModule ALL
25-
${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/scorep $<TARGET_FILE_DIR:scorep_bindings>
28+
${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/scorep $<TARGET_FILE_DIR:_bindings>
2629
COMMENT "Copying module files to build tree"
2730
)
2831

@@ -40,4 +43,4 @@ set_tests_properties(ScorepPythonTests PROPERTIES ENVIRONMENT "PYTHONPATH=${pyth
4043
set(INSTALL_DIR "lib/python${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}/site-packages")
4144

4245
install(DIRECTORY scorep DESTINATION ${INSTALL_DIR})
43-
install(TARGETS scorep_bindings DESTINATION ${INSTALL_DIR}/scorep)
46+
install(TARGETS _bindings DESTINATION ${INSTALL_DIR}/scorep)

README.md

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ To trace the full script, you need to run
4444
python -m scorep <script.py>
4545
```
4646

47-
The usual Score-P environment Variables will be respected. Please have a look at:
47+
The usual Score-P environment Variables will be respected.
48+
Please have a look at:
4849

4950
[www.vi-hps.org](http://www.vi-hps.org/projects/score-p/)
5051

@@ -62,20 +63,24 @@ python -m scorep --mpp=mpi --thread=pthread <script.py>
6263

6364
## Instrumenter
6465
The instrumenter ist the key part of the bindings.
65-
He registers with the Python tracing interface, and cares about the fowarding of events to Score-P.
66-
There are currently three different instrumenter types available as described in the following section [Instrumenter Types](#instrumenter-types) .
66+
It registers with the Python tracing interface, and cares about the fowarding of events to Score-P.
67+
There are currently five different instrumenter types available as described in the following section [Instrumenter Types](#instrumenter-types) .
6768
A user interface, to dynamically enable and disable the automatic instrumentation, using the python hooks, is also available and described under [Instrumenter User Interface](#instrumenter-user-interface)
6869

6970
### Instrumenter Types
70-
With version 2.0 of the python bindings, the term "instrumenter" is introduced. The instrumenter describes the class that maps the Python `trace` or `profile` events to Score-P. Please be aware, that `trace` and `profile` does not refer to the traditional Score-P terms of tracing and profiling, but to the Python functions [sys.settrace](https://docs.python.org/3/library/sys.html#sys.settrace) and [sys.setprofile](https://docs.python.org/3/library/sys.html#sys.setprofile).
71+
With version 2.0 of the python bindings, the term "instrumenter" is introduced.
72+
The instrumenter describes the class that maps the Python `trace` or `profile` events to Score-P.
73+
Please be aware, that `trace` and `profile` does not refer to the traditional Score-P terms of tracing and profiling, but to the Python functions [sys.settrace](https://docs.python.org/3/library/sys.html#sys.settrace) and [sys.setprofile](https://docs.python.org/3/library/sys.html#sys.setprofile).
7174

7275
The instrumenter that shall be used for tracing can be specified using `--instrumenter-type=<type>`.
73-
Currently there are the following tacers available:
76+
Currently there are the following instrumenters available:
7477
* `profile` (default) implements `call` and `return`
7578
* `trace` implements `call` and `return`
79+
* `cProfile` / `cTrace` are the same as the above but implemented in C++
7680
* `dummy` does nothing, can be used without `-m scorep` (as done by user instrumentation)
7781

7882
The `profile` instrumenter should have a smaller overhead than `trace`.
83+
Using the instrumenters implemented in C++ additionally reduces the overhead but those are only available in Python 3.
7984

8085
It is possible to disable the instrumenter passing `--noinstrumenter`.
8186
However, the [Instrumenter User Interface](#instrumenter-user-interface) may override this flag.
@@ -196,22 +201,23 @@ scorep.user.parameter_uint(name, val)
196201
scorep.user.parameter_string(name, string)
197202
```
198203

199-
where `name` defines the name of the parameter or region, while `val` or `string` represents the value that is passed to Score-P.
204+
where `name` defines the name of the parameter or region, while `val` or `string` represents the value that is passed to Score-P.
200205

201-
Disabeling the recording with Score-P is still also possilbe:
206+
Disabling the recording with Score-P is still also possible:
202207

203208
```
204209
scorep.user.enable_recording()
205210
scorep.user.disable_recording()
206211
```
207212

208-
However, please be aware that the runtime impact of disabeling Score-P is rather small, as the instrumenter is still active. For details about the instrumenter, please see [Instrumenter](#Instrumenter).
213+
However, please be aware that the runtime impact of disabling Score-P is rather small, as the instrumenter is still active.
214+
For details about the instrumenter, please see [Instrumenter](#Instrumenter).
209215

210216
## Overview about Flags
211217

212218
The following flags are special to the python bindings:
213219

214-
* `--noinstrumenter` disables the instrumentation of python code. Usefull for user instrumentation and to trace only specific code regions using `scorep.instrumenter.enable`.
220+
* `--noinstrumenter` disables the instrumentation of python code. Useful for user instrumentation and to trace only specific code regions using `scorep.instrumenter.enable`.
215221
* `--instrumenter-type=<type>` choose an instrumenter. See [Instrumenter](#Instrumenter).
216222
* `--keep-files` temporary files are kept.
217223

@@ -235,7 +241,8 @@ To disable compiler instrumentation, please specify:
235241
python -m scorep --nocompiler <script.py>
236242
```
237243

238-
For other thread schemes just specify `--thread=<something>`. E.g. :
244+
For other thread schemes just specify `--thread=<something>`.
245+
E.g. :
239246

240247
```
241248
python -m scorep --thread=omp <script.py>
@@ -246,7 +253,7 @@ Please be aware the `--user` is always passed to Score-P, as this is needed for
246253
# Compatibility
247254
## Working
248255
* python3
249-
* python2.7
256+
* python2.7, but not all features are supported
250257
* mpi using mpi4py
251258
* threaded applications
252259

benchmark/benchmark.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
44
@author: gocht
55
'''
6+
import sys
67
import benchmark_helper
78
import pickle
89

@@ -16,6 +17,9 @@
1617

1718
for test in tests:
1819
results[test] = {"profile": {}, "trace": {}, "dummy": {}, "None": {}}
20+
if sys.version_info.major >= 3:
21+
results.update({"cProfile": {}, "cTrace": {}})
22+
1923
for instrumenter in results[test]:
2024
if instrumenter == "None":
2125
enable_scorep = False
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from scorep._instrumenters.scorep_instrumenter import ScorepInstrumenter
2+
import scorep._bindings
3+
4+
5+
class ScorepCProfile(scorep._bindings.CInstrumenter, ScorepInstrumenter):
6+
def __init__(self, enable_instrumenter):
7+
scorep._bindings.CInstrumenter.__init__(self, interface='Profile')
8+
ScorepInstrumenter.__init__(self, enable_instrumenter)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from scorep._instrumenters.scorep_instrumenter import ScorepInstrumenter
2+
import scorep._bindings
3+
4+
5+
class ScorepCTrace(scorep._bindings.CInstrumenter, ScorepInstrumenter):
6+
def __init__(self, enable_instrumenter):
7+
scorep._bindings.CInstrumenter.__init__(self, interface='Trace')
8+
ScorepInstrumenter.__init__(self, enable_instrumenter)

scorep/_instrumenters/scorep_instrumenter.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import inspect
33
import os
44
from scorep._instrumenters import base_instrumenter
5-
from scorep import scorep_bindings
5+
import scorep._bindings
66

77

88
class ScorepInstrumenter(base_instrumenter.BaseInstrumenter):
@@ -58,12 +58,12 @@ def run(self, cmd, globals=None, locals=None):
5858

5959
def region_begin(self, module_name, function_name, file_name, line_number):
6060
"""Record a region begin event"""
61-
scorep_bindings.region_begin(
61+
scorep._bindings.region_begin(
6262
module_name, function_name, file_name, line_number)
6363

6464
def region_end(self, module_name, function_name):
6565
"""Record a region end event"""
66-
scorep_bindings.region_end(module_name, function_name)
66+
scorep._bindings.region_end(module_name, function_name)
6767

6868
def rewind_begin(self, name, file_name=None, line_number=None):
6969
"""
@@ -82,15 +82,15 @@ def rewind_begin(self, name, file_name=None, line_number=None):
8282
else:
8383
full_file_name = "None"
8484

85-
scorep_bindings.rewind_begin(name, full_file_name, line_number)
85+
scorep._bindings.rewind_begin(name, full_file_name, line_number)
8686

8787
def rewind_end(self, name, value):
8888
"""
8989
End of an Rewind region.
9090
@param name name of the user region
9191
@param value True or False, whenether the region shall be rewinded or not.
9292
"""
93-
scorep_bindings.rewind_end(name, value)
93+
scorep._bindings.rewind_end(name, value)
9494

9595
def oa_region_begin(self, name, file_name=None, line_number=None):
9696
"""
@@ -109,28 +109,28 @@ def oa_region_begin(self, name, file_name=None, line_number=None):
109109
else:
110110
full_file_name = "None"
111111

112-
scorep_bindings.oa_region_begin(name, full_file_name, line_number)
112+
scorep._bindings.oa_region_begin(name, full_file_name, line_number)
113113

114114
def oa_region_end(self, name):
115115
"""End an Online Access region."""
116-
scorep_bindings.oa_region_end(name)
116+
scorep._bindings.oa_region_end(name)
117117

118118
def user_enable_recording(self):
119119
"""Enable writing of trace events in ScoreP"""
120-
scorep_bindings.enable_recording()
120+
scorep._bindings.enable_recording()
121121

122122
def user_disable_recording(self):
123123
"""Disable writing of trace events in ScoreP"""
124-
scorep_bindings.disable_recording()
124+
scorep._bindings.disable_recording()
125125

126126
def user_parameter_int(self, name, val):
127127
"""Record a parameter of type integer"""
128-
scorep_bindings.parameter_int(name, val)
128+
scorep._bindings.parameter_int(name, val)
129129

130130
def user_parameter_uint(self, name, val):
131131
"""Record a parameter of type unsigned integer"""
132-
scorep_bindings.parameter_string(name, val)
132+
scorep._bindings.parameter_string(name, val)
133133

134134
def user_parameter_string(self, name, string):
135135
"""Record a parameter of type string"""
136-
scorep_bindings.parameter_string(name, string)
136+
scorep._bindings.parameter_string(name, string)

scorep/_instrumenters/scorep_profile.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import sys
44
from scorep._instrumenters.utils import get_module_name, get_file_name
55
from scorep._instrumenters.scorep_instrumenter import ScorepInstrumenter
6-
from scorep import scorep_bindings
6+
import scorep._bindings
77

88
try:
99
import threading
@@ -42,9 +42,9 @@ def _globaltrace(self, frame, why, arg):
4242
if not code.co_name == "_unsetprofile" and not modulename[:6] == "scorep":
4343
full_file_name = get_file_name(frame)
4444
line_number = code.co_firstlineno
45-
scorep_bindings.region_begin(modulename, code.co_name, full_file_name, line_number)
45+
scorep._bindings.region_begin(modulename, code.co_name, full_file_name, line_number)
4646
elif why == 'return':
4747
code = frame.f_code
4848
modulename = get_module_name(frame)
4949
if not code.co_name == "_unsetprofile" and not modulename[:6] == "scorep":
50-
scorep_bindings.region_end(modulename, code.co_name)
50+
scorep._bindings.region_end(modulename, code.co_name)

scorep/_instrumenters/scorep_trace.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import sys
44
from scorep._instrumenters.utils import get_module_name, get_file_name
55
from scorep._instrumenters.scorep_instrumenter import ScorepInstrumenter
6-
from scorep import scorep_bindings
6+
import scorep._bindings
77

88
try:
99
import threading
@@ -40,13 +40,13 @@ def _globaltrace(self, frame, why, arg):
4040
if not code.co_name == "_unsettrace" and not modulename[:6] == "scorep":
4141
full_file_name = get_file_name(frame)
4242
line_number = code.co_firstlineno
43-
scorep_bindings.region_begin(modulename, code.co_name, full_file_name, line_number)
43+
scorep._bindings.region_begin(modulename, code.co_name, full_file_name, line_number)
4444
return self._localtrace
4545
return None
4646

4747
def _localtrace(self, frame, why, arg):
4848
if why == 'return':
4949
code = frame.f_code
5050
modulename = get_module_name(frame)
51-
scorep_bindings.region_end(modulename, code.co_name)
51+
scorep._bindings.region_end(modulename, code.co_name)
5252
return self._localtrace

scorep/instrumenter.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ def get_instrumenter(enable_instrumenter=False,
2424
elif instrumenter_type == "dummy":
2525
from scorep._instrumenters.dummy import ScorepDummy
2626
global_instrumenter = ScorepDummy(enable_instrumenter)
27+
elif instrumenter_type == "cTrace":
28+
from scorep._instrumenters.scorep_cTrace import ScorepCTrace
29+
global_instrumenter = ScorepCTrace(enable_instrumenter)
30+
elif instrumenter_type == "cProfile":
31+
from scorep._instrumenters.scorep_cProfile import ScorepCProfile
32+
global_instrumenter = ScorepCProfile(enable_instrumenter)
2733
else:
2834
raise RuntimeError('instrumenter_type "{}" unkown'.format(instrumenter_type))
2935

setup.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import sys
23
from distutils.core import setup, Extension
34
import scorep.helper
45

@@ -24,8 +25,10 @@
2425
src_folder = os.path.abspath('src')
2526
include += [src_folder]
2627
sources = ['src/methods.cpp', 'src/scorep_bindings.cpp', 'src/scorepy/events.cpp']
28+
if sys.version_info.major >= 3:
29+
sources.extend(['src/classes.cpp', 'src/scorepy/cInstrumenter.cpp', 'src/scorepy/pythonHelpers.cpp'])
2730

28-
cmodules.append(Extension('scorep.scorep_bindings',
31+
cmodules.append(Extension('scorep._bindings',
2932
include_dirs=include,
3033
define_macros=[('PY_SSIZE_T_CLEAN', '1')],
3134
extra_compile_args=["-std=c++11"],

0 commit comments

Comments
 (0)