Skip to content

Add xdsl benchmark #403

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 pyperformance/data-files/benchmarks/MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ unpack_sequence <local>
unpickle <local:pickle>
unpickle_list <local:pickle>
unpickle_pure_python <local:pickle>
xdsl <local>
xml_etree <local>


Expand Down
9 changes: 9 additions & 0 deletions pyperformance/data-files/benchmarks/bm_xdsl/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[project]
name = "pyperformance_bm_xdsl"
requires-python = ">=3.10"
dependencies = ["pyperf", "xdsl==0.46.0"]
urls = {repository = "https://github.com/python/pyperformance"}
dynamic = ["version"]

[tool.pyperformance]
name = "xdsl"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
xdsl==0.46.0
107 changes: 107 additions & 0 deletions pyperformance/data-files/benchmarks/bm_xdsl/run_benchmark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
"""
Benchmark constant folding over a module of integer addition of constants using
xDSL's pattern rewriting machinery. The workload module is generated by the
``get_constant_folding_module()`` function, which is then transformed by the
``xdsl.transforms.test_constant_folding.TestConstantFoldingPass`` xDSL
transformation pass.

xDSL is a Python-native compiler framework built around SSA-based intermediate
representations. It re-implements many of MLIR's data structures and methods in
Python. This benchmark exercises the simple pattern rewriting transformation of
constant folding. This is a fair proxy for pattern rewriting transformations in
general, which are a major component of MLIR-like compilers in lowering passes.

Pattern rewriting in both xDSL and MLIR is a pointer-chasing, unstructured
workload, which makes it hard to optimise ahead-of-time. This diminishes the
traditional performance advantage of ahead-of-time compiled languages such as
C++ over dynamic languages such as Python -- making it an interesting benchmark.
More information about the design and impact of this benchmark can be found in
the Master's thesis ``Performance and Dynamism in User-extensible Compiler
Infrastructures'', which is `available on GitHub
<https://github.com/EdmundGoodman/masters-project>`_.
"""

import random

import pyperf

from xdsl.context import Context
from xdsl.dialects.arith import AddiOp, Arith, ConstantOp
from xdsl.dialects.builtin import (
Builtin,
IntegerAttr,
ModuleOp,
i32,
)
from xdsl.dialects.test import TestOp
from xdsl.ir import Operation
from xdsl.transforms.test_constant_folding import TestConstantFoldingPass


RANDOM_SEED = 0


def get_constant_folding_module(size: int = 100) -> ModuleOp:
"""Generate an integer addition constant folding workload of a given size.

The output of running the command
`print(WorkloadBuilder().constant_folding_module(size=5))` is shown
below:

```mlir
"builtin.module"() ({
%0 = "arith.constant"() {"value" = 865 : i32} : () -> i32
%1 = "arith.constant"() {"value" = 395 : i32} : () -> i32
%2 = "arith.addi"(%1, %0) : (i32, i32) -> i32
%3 = "arith.constant"() {"value" = 777 : i32} : () -> i32
%4 = "arith.addi"(%3, %2) : (i32, i32) -> i32
%5 = "arith.constant"() {"value" = 912 : i32} : () -> i32
"test.op"(%4) : (i32) -> ()
}) : () -> ()
```
"""
assert size >= 0
random.seed(RANDOM_SEED)
ops: list[Operation] = []
ops.append(ConstantOp(IntegerAttr(random.randint(1, 1000), i32)))
for i in range(1, size + 1):
if i % 2 == 0:
ops.append(AddiOp(ops[i - 1], ops[i - 2]))
else:
ops.append(ConstantOp(IntegerAttr(random.randint(1, 1000), i32)))
ops.append(TestOp([ops[(size // 2) * 2]]))
return ModuleOp(ops)


def bench_xdsl_constant_folding(loops: int, size: int) -> float:
"""Benchmark constant folding integer additions with xDSL."""
ctx = Context(allow_unregistered=True)
ctx.load_dialect(Arith)
ctx.load_dialect(Builtin)
constant_folding_pass = TestConstantFoldingPass()
constant_folding_workload = get_constant_folding_module(size)

range_it = range(loops)
t0 = pyperf.perf_counter()
for _ in range_it:
constant_folding_workload_mutable = constant_folding_workload.clone()
constant_folding_pass.apply(ctx, constant_folding_workload_mutable)
return pyperf.perf_counter() - t0


def add_cmdline_args(cmd, args):
"""Add command line arguments to a pyperf runner"""
cmd.extend(("--size", str(args.size)))


if __name__ == "__main__":
runner = pyperf.Runner(add_cmdline_args=add_cmdline_args)
runner.metadata["description"] = "Benchmark xDSL constant folding integer addition"
runner.argparser.add_argument(
"--size",
type=int,
default=1000,
help="Number of integer additions (default: 1000)",
)
args = runner.parse_args()
runner.bench_time_func("xdsl_constant_fold", bench_xdsl_constant_folding, args.size)
Loading