Skip to content

Commit 83b4310

Browse files
authored
Merge pull request #27 from score-p/scorep_5.0
Scorep 5.0
2 parents 0128c9f + 56db79f commit 83b4310

17 files changed

Lines changed: 477 additions & 635 deletions

.gitmodules

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +0,0 @@
1-
[submodule "scorep_substrate_vampir_groups_writer"]
2-
path = scorep_substrate_vampir_groups_writer
3-
url = https://github.com/score-p/scorep_substrate_vampir_groups_writer.git

README.md

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
scorep is a module that allows tracing of python scripts using [Score-P](http://www.vi-hps.org/projects/score-p/).
33

44
# Install
5-
You need to have scorep-config in your `PATH` variable.
5+
You need at least Score-P 5.0, build with `--enable-shared`.
6+
Please make sure, that `scorep-config` is in your `PATH` variable.
67

78
Then simply run
89
```
@@ -26,22 +27,27 @@ and
2627

2728
There is also a small [HowTo](https://github.com/score-p/scorep_binding_python/wiki) in the wiki.
2829

29-
# Compatibility
30-
## Working
31-
* python3
32-
* python2.7
33-
* mpi using mpi4py
30+
Since version 0.9 it is possible to pass the traditional Score-P commands to the Score-P bindings, e.g.:
3431

35-
## Not Working
36-
* python multiprocessing
37-
* Score-P does currently not support any non MPI or non SHMEM communication. So the different processes will not know from each other. You might want to take a look to https://mpi4py.readthedocs.io/en/stable/mpi4py.futures.html .
32+
```
33+
python -m scorep --mpp=mpi --thread=pthread <script.py>
34+
```
3835

39-
## Partialy working
40-
* threaded applications
41-
* Please have a look to a Score-P trunk package with revision at least 13560 here:
42-
http://scorepci.pages.jsc.fz-juelich.de/scorep-pipelines/.
43-
44-
# User instrumentation
36+
To see all flags simply call:
37+
38+
```
39+
scorep --help
40+
```
41+
42+
## MPI
43+
44+
To use trace an MPI parallel application, please specify
45+
46+
```
47+
python -m scorep --mpp=mpi <script.py>
48+
```
49+
50+
## User instrumentation
4551

4652
In some cases, the user might want to define a region, log some parameters, or just disable tracing for a certain area. To do so the module implements a few functions:
4753

@@ -52,7 +58,6 @@ scorep.user.region_end(name)
5258

5359
These functions allow the definition of user regions. `name` defines the name of a region. Each `user.region_begin` shall have a corresponding call to `user.region_end`.
5460

55-
5661
```
5762
scorep.user.enable_recording()
5863
scorep.user.disable_recording()
@@ -67,16 +72,52 @@ scorep.user.parameter_string(name, string)
6772
```
6873

6974
These functions allow passing user parameters to Score-P. These parameters can be int, uint and string. `name` defines the name of the parameter, while `val` or `string` defines the value that is passed to Score-P.
75+
Please be aware, that the scorep module still needs to be preloaded, i.e. by using `python -m scorep`.
7076

71-
# Tracing
72-
The tracing uses Score-P User instrumentation. The python trace module was reworked, to pass the region names to ```SCOREP_USER_REGION_BEGIN``` and ```SCOREP_USER_REGION_END``` instead of printing. All other features of the tracing module where striped.
77+
## Additional Flags
7378

74-
# MPI
79+
The Score-P bindings now also support a `--nopython` flag, which disables the python instrumentation.
80+
This might be helpful, if only user instrumentation is required, or only some instrumented libraries shall be traced.
7581

76-
This version of the Score-P python tracing plugin supports MPI. To use it please specify `--mpi`:
82+
## Backward Compatibility
83+
84+
In order to maintain backwards Compatibility, the following flags are set per default:
7785

7886
```
79-
python -m scorep --mpi <script.py>
87+
python -m scorep --compiler --thread=pthread <script.py>
8088
```
8189

82-
This will ensure, that the right Score-P libs are in `LD_PRELOAD`. It will re-execute the tracing script, with the preloaded libs.
90+
The traditional `--mpi` does still work, and is similar to the following call:
91+
92+
```
93+
python -m scorep --compiler --thread=pthread --mpp=mpi <script.py>
94+
```
95+
96+
To disable compiler instrumentation please specify:
97+
98+
```
99+
python -m scorep --nocompiler <script.py>
100+
```
101+
102+
For other thread schemes just specify `--thread=<something>`. E.g. :
103+
104+
```
105+
python -m scorep --thread=omp <script.py>
106+
```
107+
108+
Please be aware the `--user` is always passed to Score-P, as this is needed for the python instrumentation.
109+
110+
# Compatibility
111+
## Working
112+
* python3
113+
* python2.7
114+
* mpi using mpi4py
115+
* threaded applications
116+
117+
118+
## Not Working
119+
* python multiprocessing
120+
* Score-P does currently not support any non MPI or non SHMEM communication. So the different processes will not know from each other. You might want to take a look to https://mpi4py.readthedocs.io/en/stable/mpi4py.futures.html .
121+
122+
# Tracing
123+
The tracing uses Score-P User instrumentation. The python trace module was reworked, to pass the region names to `SCOREP_USER_REGION_BEGIN` and `SCOREP_USER_REGION_END` instead of printing. All other features of the tracing module where striped.

scorep/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__all__ = ["trace", "scorep_bindings", "user"]
1+
__all__ = ["trace", "scorep_bindings", "user", "subsystem"]

scorep/__main__.py

Lines changed: 72 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -5,97 +5,102 @@
55

66
import scorep.trace
77
import scorep.helper
8+
import scorep.subsystem
89

910

1011
def _usage(outfile):
1112
outfile.write("""TODO
1213
""" % sys.argv[0])
1314

1415

15-
global_trace = None
16-
1716
cuda_support = None
1817
opencl_support = None
1918

19+
2020
def _err_exit(msg):
2121
sys.stderr.write("%s: %s\n" % ("scorep", msg))
2222
sys.exit(1)
2323

2424

25-
def set_init_environment(mpi):
25+
def set_init_environment(scorep_config=[], keep_files=False):
2626
"""
2727
Set the inital needed environmet variables, to get everythin up an running.
2828
As a few variables interact with LD env vars, the programms needs to be restarted after this.
2929
The function set the env var `SCOREP_PYTHON_BINDINGS_INITALISED` to true, once it is done with
3030
initalising.
3131
32-
@param mpi indicates if mpi is used.
32+
@param scorep_config configuration flags for score-p
33+
@param keep_files whether to keep the generated files, or not.
34+
@return temp_dir to be deleted once the script is done
3335
"""
3436

35-
"""
36-
look for vampir_groups_writer, which will produce a groups file for vampir.
37-
This allows collored traces.
38-
"""
39-
vampir_groups_writer_lib = "libscorep_substrate_vampir_groups_writer.so"
40-
vampir_groups_writer = scorep.helper.find_lib(vampir_groups_writer_lib)
41-
42-
if vampir_groups_writer:
43-
scorep.helper.add_to_ld_library_path(
44-
os.path.dirname(vampir_groups_writer))
45-
if ("SCOREP_SUBSTRATE_PLUGINS" not in os.environ) or (
46-
os.environ["SCOREP_SUBSTRATE_PLUGINS"] == ""):
47-
os.environ["SCOREP_SUBSTRATE_PLUGINS"] = "vampir_groups_writer"
48-
else:
49-
os.environ["SCOREP_SUBSTRATE_PLUGINS"] += ",vampir_groups_writer"
37+
if ("LD_PRELOAD" in os.environ) and (
38+
"libscorep" in os.environ["LD_PRELOAD"]):
39+
raise RuntimeError(
40+
"Score-P is already loaded. This should not happen at this point")
5041

51-
if mpi:
52-
if ("LD_PRELOAD" not in os.environ) or (
53-
"libscorep" not in os.environ["LD_PRELOAD"]):
42+
subsystem_lib_name, temp_dir = scorep.subsystem.generate(
43+
scorep_config, keep_files)
44+
scorep_ld_preload = scorep.helper.generate_ld_preload(scorep_config)
5445

55-
ld_preload, scorep_subsystem = scorep.helper.generate_ld_preload()
56-
scorep.helper.add_to_ld_library_path(
57-
os.path.dirname(scorep_subsystem))
58-
59-
os.environ["LD_PRELOAD"] = ld_preload + " " + os.environ["LD_PRELOAD"]
46+
scorep.helper.add_to_ld_library_path(temp_dir)
6047

48+
preload_str = scorep_ld_preload + " " + subsystem_lib_name
49+
if "LD_PRELOAD" in os.environ:
50+
print("LD_PRELOAD is already specified. If Score-P is already loaded this might lead to errors.", file=sys.stderr)
51+
preload_str = preload_str + " " + os.environ["LD_PRELOAD"]
52+
os.environ["LD_PRELOAD"] = preload_str
6153
os.environ["SCOREP_PYTHON_BINDINGS_INITALISED"] = "true"
6254

6355

6456
def scorep_main(argv=None):
65-
global target_code
57+
# print(sys.flags)
6658
if argv is None:
6759
argv = sys.argv
68-
try:
69-
opts, prog_argv = getopt.getopt(argv[1:], "v",
70-
["help", "version", "mpi"])
71-
72-
except getopt.error as msg:
73-
sys.stderr.write("%s: %s\n" % (sys.argv[0], msg))
74-
sys.stderr.write("Try `%s --help' for more information\n"
75-
% sys.argv[0])
76-
sys.exit(1)
77-
78-
mpi = False
7960

80-
for opt in opts:
81-
key, value = opt
82-
if key == "--help":
83-
_usage(sys.stdout)
84-
sys.exit(0)
61+
scorep_config = []
62+
prog_argv = []
63+
parse_scorep_commands = True
64+
65+
keep_files = False
66+
no_default_threads = False
67+
no_default_compiler = False
68+
no_python = False
69+
70+
for elem in argv[1:]:
71+
if parse_scorep_commands:
72+
if elem == "--mpi":
73+
scorep_config.append("--mpp=mpi")
74+
elif elem == "--keep-files":
75+
keep_files = True
76+
elif "--thread=" in elem:
77+
scorep_config.append(elem)
78+
no_default_threads = True
79+
elif elem == "--nocompiler":
80+
scorep_config.append(elem)
81+
no_default_compiler = True
82+
elif elem == "--nopython":
83+
no_python = True
84+
elif elem[0] == "-":
85+
scorep_config.append(elem)
86+
else:
87+
prog_argv.append(elem)
88+
parse_scorep_commands = False
89+
else:
90+
prog_argv.append(elem)
8591

86-
if key == "--version":
87-
sys.stdout.write("scorep_trace 1.0\n")
88-
sys.exit(0)
92+
if not no_default_threads:
93+
scorep_config.append("--thread=pthread")
8994

90-
if key == "--mpi":
91-
mpi = True
95+
if not no_default_compiler:
96+
scorep_config.append("--compiler")
9297

9398
if len(prog_argv) == 0:
94-
_err_exit("missing name of file to run")
99+
_err_exit("Did not find a script to run")
95100

96101
if ("SCOREP_PYTHON_BINDINGS_INITALISED" not in os.environ) or (
97102
os.environ["SCOREP_PYTHON_BINDINGS_INITALISED"] != "true"):
98-
set_init_environment(mpi)
103+
set_init_environment(scorep_config, keep_files)
99104

100105
"""
101106
python -m starts the module as skript. i.e. sys.argv will loke like:
@@ -111,23 +116,14 @@ def scorep_main(argv=None):
111116
new_args.append(elem)
112117
os.execve(sys.executable, new_args, os.environ)
113118

114-
scorep_bindings = None
115-
if mpi:
116-
try:
117-
scorep_bindings = importlib.import_module(
118-
"scorep.scorep_bindings_mpi")
119-
except ModuleNotFoundError:
120-
raise ModuleNotFoundError(
121-
"The MPI bindings are missing. Did you build Score-P with '--without-mpi'?")
122-
else:
123-
scorep_bindings = importlib.import_module("scorep.scorep_bindings")
119+
scorep_bindings = importlib.import_module("scorep.scorep_bindings")
124120

125121
# everything is ready
126122
sys.argv = prog_argv
127123
progname = prog_argv[0]
128124
sys.path[0] = os.path.split(progname)[0]
129125

130-
global_trace = scorep.trace.ScorepTrace(scorep_bindings, True)
126+
tracer = scorep.trace.ScorepTrace(scorep_bindings, not no_python)
131127
try:
132128
with open(progname) as fp:
133129
code = compile(fp.read(), progname, 'exec')
@@ -139,32 +135,30 @@ def scorep_main(argv=None):
139135
'__package__': None,
140136
'__cached__': None,
141137
}
142-
143-
global_trace.runctx(code, globs, globs)
138+
139+
tracer.runctx(code, globs, globs)
144140
except OSError as err:
145141
_err_exit("Cannot run file %r because: %s" % (sys.argv[0], err))
146-
except SystemExit:
147-
pass
142+
finally:
143+
scorep.subsystem.clean_up(keep_files)
144+
148145

149146
def main(argv=None):
150147
import traceback
151148
call_stack = traceback.extract_stack()
152149
call_stack_array = traceback.format_list(call_stack)
153150
call_stack_string = ""
154151
for elem in call_stack_array[:-1]:
155-
call_stack_string+=elem
156-
_err_exit("Someone called scorep.__main__.main(argv).\n"
157-
"This is not supposed to happen, but might be triggered, if your application calls \"sys.modules['__main__'].main\".\n"
158-
"This python stacktrace might be helpfull to find the reason:\n%s" % call_stack_string)
152+
call_stack_string += elem
153+
_err_exit(
154+
"Someone called scorep.__main__.main(argv).\n"
155+
"This is not supposed to happen, but might be triggered, if your application calls \"sys.modules['__main__'].main\".\n"
156+
"This python stacktrace might be helpfull to find the reason:\n%s" %
157+
call_stack_string)
158+
159159

160160
if __name__ == '__main__':
161161
scorep_main()
162-
163162
else:
164-
'''
165-
If Score-P is not intialised using the tracing module (`python -m scorep <script.py>`),
166-
we need to make sure that, if a user call gets called, scorep is still loaded.
167-
Moreover, if the module is loaded with `import scorep` we can't do any mpi support anymore
168-
'''
169-
scorep_bindings = importlib.import_module("scorep.scorep_bindings")
170-
global_trace = scorep.trace.ScorepTrace(scorep_bindings, False)
163+
if ("SCOREP_PYTHON_BINDINGS_INITALISED" not in os.environ) or (os.environ["SCOREP_PYTHON_BINDINGS_INITALISED"] != "true"):
164+
print("scorep needs to be loaded using \"python -m scorep <script>\". Please be aware that scorep might not work correctly!", file=sys.stderr)

0 commit comments

Comments
 (0)