Skip to content

Commit be7166a

Browse files
Andrija Kolicansalond
authored andcommitted
[GR-71617] Port 'pyperformance' and 'numpy' benchmarks to PolyBench
PullRequest: graalpython/4254
2 parents eccb988 + 98cbc4e commit be7166a

96 files changed

Lines changed: 14511 additions & 7 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Copyright (c) 2005-2025, NumPy Developers.
2+
All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without
5+
modification, are permitted provided that the following conditions are
6+
met:
7+
8+
* Redistributions of source code must retain the above copyright
9+
notice, this list of conditions and the following disclaimer.
10+
11+
* Redistributions in binary form must reproduce the above
12+
copyright notice, this list of conditions and the following
13+
disclaimer in the documentation and/or other materials provided
14+
with the distribution.
15+
16+
* Neither the name of the NumPy Developers nor the names of any
17+
contributors may be used to endorse or promote products derived
18+
from this software without specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Numpy benchmark port process for benchmarking with the PolyBench harness
2+
3+
## Brief explanation
4+
5+
These PolyBench benchmarks have been manually generated for the file `bench_core.py`
6+
that was copied from the `numpy` repository.
7+
Each benchmark file maps 1:1 to a `test_*` method of a `Benchmark` extending class
8+
inside `bench_core.py` and the files are named following the pattern of `<file>-<class>-<method>.py`
9+
- e.g. the PolyBench benchmark file `bench_core.Core.time_array_1.py` corresponds to
10+
the `time_array_1` method of the `Core` class which is defined in the `bench_core.py` file.
11+
12+
If required, the imported set of benchmarks could be expanded to other numpy benchmarks analogously.
13+
14+
## Version information
15+
16+
Version: 1.26.4
17+
Source repository: https://github.com/numpy/numpy
18+
19+
The version was chosen to align with the one used in `graalpython/mx.graalpython/mx_graalpython_python_benchmarks.py::NumPySuite`.
20+
21+
## Files sourced from the numpy project
22+
23+
### bench_core.py
24+
Original file path: numpy/benchmarks/benchmarks/bench_core.py
25+
Changes made to the original file, as reported by the `diff` tool:
26+
```
27+
1,2c1,2
28+
< from .common import Benchmark
29+
<
30+
---
31+
> import sys
32+
> import os
33+
3a4,5
34+
> sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
35+
> from common import Benchmark
36+
4a7,8
37+
> # Ensure we have numpy version info in the logs
38+
> print(f"Using numpy version '{np.__version__}'")
39+
```
40+
41+
### common.py
42+
Original file path: numpy/benchmarks/benchmarks/common.py
43+
No modifications made.
44+
45+
### License.txt
46+
The BSD 3-clause license copied from the numpy repository.
47+
48+
## Original files necessary for benchmarking with the PolyBench harness
49+
50+
### `<file>-<class>-<method>.py` files
51+
These are new files that do not have a corresponding match in the numpy repository.
52+
They are thus licensed under the Oracle UPL license used elsewhere in this repository.
53+
These files are generated to conform to the expectations of the PolyBench harness.
54+
These files were generated with the help of a generative AI model using the following pattern:
55+
```
56+
# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
57+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
58+
#
59+
# The Universal Permissive License (UPL), Version 1.0
60+
#
61+
# Subject to the condition set forth below, permission is hereby granted to any
62+
# person obtaining a copy of this software, associated documentation and/or
63+
# data (collectively the "Software"), free of charge and under any and all
64+
# copyright rights in the Software, and any and all patent rights owned or
65+
# freely licensable by each licensor hereunder covering either (i) the
66+
# unmodified Software as contributed to or provided by such licensor, or (ii)
67+
# the Larger Works (as defined below), to deal in both
68+
#
69+
# (a) the Software, and
70+
#
71+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
72+
# one is included with the Software each a "Larger Work" to which the Software
73+
# is contributed by such licensors),
74+
#
75+
# without restriction, including without limitation the rights to copy, create
76+
# derivative works of, display, perform, and distribute the Software and make,
77+
# use, sell, offer for sale, import, export, have made, and have sold the
78+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
79+
# either these or other terms.
80+
#
81+
# This license is subject to the following condition:
82+
#
83+
# The above copyright notice and either this complete permission notice or at a
84+
# minimum a reference to the UPL must be included in all copies or substantial
85+
# portions of the Software.
86+
#
87+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
88+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
89+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
90+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
91+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
92+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
93+
# SOFTWARE.
94+
95+
import sys
96+
import os
97+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
98+
99+
LOOP_COUNT = <LOOP_COUNT_VALUE>
100+
<BENCH_SOURCE_CLASS_INSTANCE> = None
101+
102+
103+
def setup():
104+
from <BENCH_SOURCE_FILE> import <BENCH_SOURCE_CLASS>
105+
global <BENCH_SOURCE_CLASS_INSTANCE>
106+
<BENCH_SOURCE_CLASS_INSTANCE> = <BENCH_SOURCE_CLASS>()
107+
<BENCH_SOURCE_CLASS_INSTANCE>.setup()
108+
109+
110+
def __benchmark__():
111+
# Original workload
112+
<BENCH_SOURCE_CLASS_INSTANCE>.<BENCH_SOURCE_METHOD>()
113+
114+
115+
def run():
116+
for _ in range(LOOP_COUNT):
117+
__benchmark__()
118+
119+
120+
def warmupIterations():
121+
return 0
122+
123+
124+
def iterations():
125+
return 10
126+
127+
128+
def summary():
129+
return {
130+
"name": "OutlierRemovalAverageSummary",
131+
"lower-threshold": 0.0,
132+
"upper-threshold": 1.0,
133+
}
134+
135+
136+
def dependencies():
137+
# Required alongside this file if copied elsewhere
138+
return ["<BENCH_SOURCE_FILE>.py", "common.py"]
139+
140+
```
141+
Where:
142+
* `<BENCH_SOURCE_CLASS_INSTANCE>` is a global variable that stores the instance of the benchmark class.
143+
* `<BENCH_SOURCE_FILE>` is the name of the benchmark file (without the extension, e.g. `bench_core`).
144+
* `<BENCH_SOURCE_CLASS>` is the benchmark class (e.g. `Core`).
145+
* `<BENCH_SOURCE_METHOD>` is the benchmark method (e.g. `time_array_1`).
146+
* `<LOOP_COUNT_VALUE>` is a number tweaked to ensure a workload long enough to minimize noise.
147+
The value was initially set by the AI model and subsequently tweaked by hand.
148+
The value was tweaked so that the benchmark executes somewhere in the range between 10ms and 1s.
149+
150+
This template is not exhaustive and is provided for the purpose of facilitating maintenance.
151+
There are multiple edge-cases one has to consider when generating a benchmark file:
152+
* The benchmark class might not implement the `setup` method.
153+
* The benchmark method might require arguments to be passed.
154+
In such cases, the values were chosen from the `params` field of the benchmark class and stored
155+
as global constants next to the `LOOP_COUNT` constant.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
2+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
#
4+
# The Universal Permissive License (UPL), Version 1.0
5+
#
6+
# Subject to the condition set forth below, permission is hereby granted to any
7+
# person obtaining a copy of this software, associated documentation and/or
8+
# data (collectively the "Software"), free of charge and under any and all
9+
# copyright rights in the Software, and any and all patent rights owned or
10+
# freely licensable by each licensor hereunder covering either (i) the
11+
# unmodified Software as contributed to or provided by such licensor, or (ii)
12+
# the Larger Works (as defined below), to deal in both
13+
#
14+
# (a) the Software, and
15+
#
16+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
17+
# one is included with the Software each a "Larger Work" to which the Software
18+
# is contributed by such licensors),
19+
#
20+
# without restriction, including without limitation the rights to copy, create
21+
# derivative works of, display, perform, and distribute the Software and make,
22+
# use, sell, offer for sale, import, export, have made, and have sold the
23+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
24+
# either these or other terms.
25+
#
26+
# This license is subject to the following condition:
27+
#
28+
# The above copyright notice and either this complete permission notice or at a
29+
# minimum a reference to the UPL must be included in all copies or substantial
30+
# portions of the Software.
31+
#
32+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38+
# SOFTWARE.
39+
40+
import sys
41+
import os
42+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
43+
44+
LOOP_COUNT = 100000
45+
_core = None
46+
47+
48+
def setup():
49+
from bench_core import Core
50+
global _core
51+
_core = Core()
52+
_core.setup()
53+
54+
55+
def __benchmark__():
56+
# Original workload
57+
_core.time_arange_100()
58+
59+
60+
def run():
61+
for _ in range(LOOP_COUNT):
62+
__benchmark__()
63+
64+
65+
def warmupIterations():
66+
return 0
67+
68+
69+
def iterations():
70+
return 10
71+
72+
73+
def summary():
74+
return {
75+
"name": "OutlierRemovalAverageSummary",
76+
"lower-threshold": 0.0,
77+
"upper-threshold": 1.0,
78+
}
79+
80+
81+
def dependencies():
82+
# Required alongside this file if copied elsewhere
83+
return ["bench_core.py", "common.py"]
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
2+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
#
4+
# The Universal Permissive License (UPL), Version 1.0
5+
#
6+
# Subject to the condition set forth below, permission is hereby granted to any
7+
# person obtaining a copy of this software, associated documentation and/or
8+
# data (collectively the "Software"), free of charge and under any and all
9+
# copyright rights in the Software, and any and all patent rights owned or
10+
# freely licensable by each licensor hereunder covering either (i) the
11+
# unmodified Software as contributed to or provided by such licensor, or (ii)
12+
# the Larger Works (as defined below), to deal in both
13+
#
14+
# (a) the Software, and
15+
#
16+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
17+
# one is included with the Software each a "Larger Work" to which the Software
18+
# is contributed by such licensors),
19+
#
20+
# without restriction, including without limitation the rights to copy, create
21+
# derivative works of, display, perform, and distribute the Software and make,
22+
# use, sell, offer for sale, import, export, have made, and have sold the
23+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
24+
# either these or other terms.
25+
#
26+
# This license is subject to the following condition:
27+
#
28+
# The above copyright notice and either this complete permission notice or at a
29+
# minimum a reference to the UPL must be included in all copies or substantial
30+
# portions of the Software.
31+
#
32+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38+
# SOFTWARE.
39+
40+
import sys
41+
import os
42+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
43+
44+
LOOP_COUNT = 1_000_000
45+
_core = None
46+
47+
48+
def setup():
49+
from bench_core import Core
50+
global _core
51+
_core = Core()
52+
_core.setup()
53+
54+
55+
def __benchmark__():
56+
# Original workload
57+
_core.time_array_1()
58+
59+
60+
def run():
61+
for _ in range(LOOP_COUNT):
62+
__benchmark__()
63+
64+
65+
def warmupIterations():
66+
return 0
67+
68+
69+
def iterations():
70+
return 10
71+
72+
73+
def summary():
74+
return {
75+
"name": "OutlierRemovalAverageSummary",
76+
"lower-threshold": 0.0,
77+
"upper-threshold": 1.0,
78+
}
79+
80+
81+
def dependencies():
82+
# Required alongside this file if copied elsewhere
83+
return ["bench_core.py", "common.py"]

0 commit comments

Comments
 (0)