Skip to content

Commit 3abdb1a

Browse files
authored
Merge branch 'score-p:master' into instrumenter_file
2 parents 7a2a6c6 + 48cecbb commit 3abdb1a

8 files changed

Lines changed: 192 additions & 53 deletions

File tree

benchmark/bm_baseline.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22

33
result = 0
44
iterations = int(sys.argv[1])
5-
iteration_list = list(range(iterations))
65

7-
for i in iteration_list:
6+
for i in range(iterations):
87
result += 1
98

109
assert(result == iterations)

benchmark/bm_simplefunc.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
'''
2-
Created on 04.10.2019
3-
4-
@author: gocht
5-
'''
61
import sys
72

83

@@ -12,9 +7,8 @@ def add(val):
127

138
result = 0
149
iterations = int(sys.argv[1])
15-
iteration_list = list(range(iterations))
1610

17-
for i in iteration_list:
11+
for i in range(iterations):
1812
result = add(result)
1913

2014
assert(result == iterations)

benchmark/compare.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import argparse
2+
import pickle
3+
import numpy
4+
5+
parser = argparse.ArgumentParser(description='Compare two benchmarks.',
6+
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
7+
parser.add_argument('left', help='First input for comparison')
8+
parser.add_argument('right', help='Second input for comparison')
9+
parser.add_argument('-s', help='short output', action='store_false')
10+
args = parser.parse_args()
11+
12+
13+
with open(args.left, "rb") as f:
14+
left = pickle.load(f)
15+
16+
with open(args.right, "rb") as f:
17+
right = pickle.load(f)
18+
19+
if left.keys() != right.keys():
20+
raise ValueError("Different Experiments")
21+
22+
experiment = right.keys()
23+
24+
for exp in experiment:
25+
print("\nExperiment: {}".format(exp))
26+
if left[exp].keys() != right[exp].keys():
27+
raise ValueError("Different Instrumenters")
28+
instrumenters = left[exp].keys()
29+
30+
for inst in instrumenters:
31+
print("\n\tInstrumenter: {}".format(inst))
32+
if left[exp][inst].keys() != right[exp][inst].keys():
33+
raise ValueError("Different Iterations")
34+
iterations = left[exp][inst].keys()
35+
Y_left = []
36+
Y_right = []
37+
X = []
38+
for it in iterations:
39+
left_val = left[exp][inst][it]
40+
right_val = right[exp][inst][it]
41+
if len(left_val) != len(right_val):
42+
raise ValueError("Different Repetitons")
43+
44+
Y_left.append(numpy.mean(left_val))
45+
Y_right.append(numpy.mean(right_val))
46+
X.append(numpy.full([1], it))
47+
48+
if args.s:
49+
print("\t\tInterations {}".format(it))
50+
print("\t\tMean: {:>7.4f} s {:>7.4f} s".format(numpy.mean(left_val), numpy.mean(right_val)))
51+
print("\t\tMedian: {:>7.4f} s {:>7.4f} s".format(
52+
numpy.quantile(left_val, 0.50), numpy.quantile(right_val, 0.50)))
53+
print("\t\t5%: {:>7.4f} s {:>7.4f} s".format(
54+
numpy.quantile(left_val, 0.05), numpy.quantile(right_val, 0.05)))
55+
print("\t\t95%: {:>7.4f} s {:>7.4f} s".format(
56+
numpy.quantile(left_val, 0.95), numpy.quantile(right_val, 0.95)))
57+
Y_left = numpy.asarray(Y_left, dtype=float).flatten()
58+
Y_right = numpy.asarray(Y_right, dtype=float).flatten()
59+
X = numpy.asarray(X, dtype=float).flatten()
60+
61+
cost_left = numpy.polyfit(X, Y_left, 1)
62+
cost_right = numpy.polyfit(X, Y_right, 1)
63+
64+
if args.s:
65+
print("")
66+
print("\tSlope {:>7.4f} us {:>7.4f} us".format(cost_left[0] * 1e6, cost_right[0] * 1e6))
67+
print("\tIntercept {:>7.4f} s {:>7.4f} s".format(cost_left[1], cost_right[1]))

benchmark/compare_commits.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
3+
wd=`pwd`
4+
root_dir=`realpath "$wd/../"`
5+
6+
echo $wd
7+
echo $root_dir
8+
9+
function benchmark_branch {
10+
cd $root_dir
11+
git checkout $1
12+
head=`git rev-parse --short HEAD`
13+
pip install .
14+
cd $wd
15+
python benchmark.py -o result-$1-$head.pkl
16+
}
17+
18+
sleep 5
19+
benchmark_branch $1
20+
sleep 5
21+
benchmark_branch $2
22+

benchmark/run.sh

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@
99
#SBATCH --comment=no_monitoring
1010
#SBATCH --job-name benchmark_python
1111

12-
module load Python/3.6.4-intel-2018a
13-
module unload intel
14-
module load intel
12+
module load Python/3.8.6-GCCcore-10.2.0
13+
module load Score-P/7.0-gompic-2020b
1514

16-
export PATH=/scratch/rschoene/scorep-6-inst/bin:$PATH
15+
env_dir=~/virtenv/p-3.8.6-GCCcore-10.2.0-scorep-7.0-gompic-2020b/
1716

18-
. ~/scorep_binding_python/test/bin/activate
17+
if [ ! -d $env_dir ]
18+
then
19+
echo "Please create virtual env under: $env_dir"
20+
exit -1
21+
fi
1922

20-
srun python benchmark.py
23+
source $env_dir/bin/activate
24+
25+
srun compare_commits.sh master faster

src/scorepy/cInstrumenter.cpp

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -115,31 +115,39 @@ bool CInstrumenter::on_event(PyFrameObject& frame, int what, PyObject*)
115115
case PyTrace_CALL:
116116
{
117117
const PyCodeObject& code = *frame.f_code;
118-
const char* name = PyUnicode_AsUTF8(code.co_name);
119-
const char* module_name = get_module_name(frame);
120-
assert(name);
121-
assert(module_name);
122-
// TODO: Use string_view/CString comparison?
123-
if (std::string(name) != "_unsetprofile" && std::string(module_name, 0, 6) != "scorep")
118+
bool success = try_region_begin(reinterpret_cast<std::uintptr_t>(&code));
119+
if (!success)
124120
{
125-
const int line_number = code.co_firstlineno;
126-
const auto file_name = get_file_name(frame);
127-
region_begin(name, module_name, file_name, line_number,
128-
reinterpret_cast<std::uintptr_t>(&code));
121+
const char* name = PyUnicode_AsUTF8(code.co_name);
122+
const char* module_name = get_module_name(frame);
123+
assert(name);
124+
assert(module_name);
125+
// TODO: Use string_view/CString comparison?
126+
if (std::string(name) != "_unsetprofile" && std::string(module_name, 0, 6) != "scorep")
127+
{
128+
const int line_number = code.co_firstlineno;
129+
const std::string file_name = get_file_name(frame);
130+
region_begin(name, module_name, file_name, line_number,
131+
reinterpret_cast<std::uintptr_t>(&code));
132+
}
129133
}
130134
break;
131135
}
132136
case PyTrace_RETURN:
133137
{
134138
const PyCodeObject& code = *frame.f_code;
135-
const char* name = PyUnicode_AsUTF8(code.co_name);
136-
const char* module_name = get_module_name(frame);
137-
assert(name);
138-
assert(module_name);
139-
// TODO: Use string_view/CString comparison?
140-
if (std::string(name) != "_unsetprofile" && std::string(module_name, 0, 6) != "scorep")
139+
bool success = try_region_end(reinterpret_cast<std::uintptr_t>(&code));
140+
if (!success)
141141
{
142-
region_end(name, module_name, reinterpret_cast<std::uintptr_t>(&code));
142+
const char* name = PyUnicode_AsUTF8(code.co_name);
143+
const char* module_name = get_module_name(frame);
144+
assert(name);
145+
assert(module_name);
146+
// TODO: Use string_view/CString comparison?
147+
if (std::string(name) != "_unsetprofile" && std::string(module_name, 0, 6) != "scorep")
148+
{
149+
region_end(name, module_name, reinterpret_cast<std::uintptr_t>(&code));
150+
}
143151
}
144152
break;
145153
}

src/scorepy/events.cpp

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,16 @@
1-
#include "events.hpp"
2-
#include <Python.h>
31
#include <algorithm>
42
#include <array>
53
#include <iostream>
6-
#include <scorep/SCOREP_User_Functions.h>
7-
#include <scorep/SCOREP_User_Variables.h>
8-
#include <unordered_map>
94

10-
namespace scorepy
11-
{
5+
#include <Python.h>
126

13-
struct region_handle
14-
{
15-
constexpr region_handle() = default;
16-
~region_handle() = default;
17-
constexpr bool operator==(const region_handle& other)
18-
{
19-
return this->value == other.value;
20-
}
21-
SCOREP_User_RegionHandle value = SCOREP_USER_INVALID_REGION;
22-
};
7+
#include "events.hpp"
8+
#include "pythonHelpers.hpp"
239

24-
constexpr region_handle uninitialised_region_handle = region_handle();
10+
namespace scorepy
11+
{
2512

26-
static std::unordered_map<std::uintptr_t, region_handle> regions;
13+
std::unordered_map<std::uintptr_t, region_handle> regions;
2714
static std::unordered_map<std::string, region_handle> user_regions;
2815
static std::unordered_map<std::string, region_handle> rewind_regions;
2916

src/scorepy/events.hpp

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,32 @@
11
#pragma once
2-
32
#include <cstdint>
43
#include <string>
4+
#include <unordered_map>
5+
6+
#include <scorep/SCOREP_User_Functions.h>
7+
#include <scorep/SCOREP_User_Variables.h>
58

69
namespace scorepy
710
{
11+
12+
struct region_handle
13+
{
14+
constexpr region_handle() = default;
15+
~region_handle() = default;
16+
constexpr bool operator==(const region_handle& other)
17+
{
18+
return this->value == other.value;
19+
}
20+
constexpr bool operator!=(const region_handle& other)
21+
{
22+
return this->value != other.value;
23+
}
24+
25+
SCOREP_User_RegionHandle value = SCOREP_USER_INVALID_REGION;
26+
};
27+
28+
constexpr region_handle uninitialised_region_handle = region_handle();
29+
830
/// Combine the arguments into a region name
931
/// Return value is a statically allocated string to avoid memory (re)allocations
1032
inline const std::string& make_region_name(const std::string& module_name, const std::string& name)
@@ -16,12 +38,48 @@ inline const std::string& make_region_name(const std::string& module_name, const
1638
return region;
1739
}
1840

41+
extern std::unordered_map<std::uintptr_t, region_handle> regions;
42+
43+
/** tries to enter a region. Return true on success
44+
*
45+
*/
46+
inline bool try_region_begin(std::uintptr_t identifier)
47+
{
48+
auto it = regions.find(identifier);
49+
if (it != regions.end())
50+
{
51+
SCOREP_User_RegionEnter(it->second.value);
52+
return true;
53+
}
54+
else
55+
{
56+
return false;
57+
}
58+
}
59+
1960
void region_begin(const std::string& function_name, const std::string& module,
2061
const std::string& file_name, const std::uint64_t line_number,
2162
const std::uintptr_t& identifier);
2263
void region_begin(const std::string& function_name, const std::string& module,
2364
const std::string& file_name, const std::uint64_t line_number);
2465

66+
/** tries to end a region. Return true on success
67+
*
68+
*/
69+
inline bool try_region_end(std::uintptr_t identifier)
70+
{
71+
auto it_region = regions.find(identifier);
72+
if (it_region != regions.end())
73+
{
74+
SCOREP_User_RegionEnd(it_region->second.value);
75+
return true;
76+
}
77+
else
78+
{
79+
return false;
80+
}
81+
}
82+
2583
void region_end(const std::string& function_name, const std::string& module,
2684
const std::uintptr_t& identifier);
2785
void region_end(const std::string& function_name, const std::string& module);
@@ -34,5 +92,4 @@ void rewind_end(std::string region_name, bool value);
3492
void parameter_int(std::string name, int64_t value);
3593
void parameter_uint(std::string name, uint64_t value);
3694
void parameter_string(std::string name, std::string value);
37-
3895
} // namespace scorepy

0 commit comments

Comments
 (0)