Skip to content
Draft
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
11 changes: 11 additions & 0 deletions benchmarks/benchmark_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,17 @@ def workload_field_params(workloads: list, keys: tuple) -> list:
)
return params


def torch_inductor_baseline(fn: Callable) -> Callable:
"""Compile a benchmark-local PyTorch baseline with TorchInductor.

The baseline implementation itself stays in the benchmark file so tests do
not become performance oracles. This helper only centralizes the compile
policy used by common-op benchmark baselines.
"""
return torch.compile(fn, fullgraph=True)


class ManifestBenchmark(BenchmarkBase[ShapeDtypeWorkload]):
"""Generic benchmark that reads FLOP/memory counts from an Op instance.

Expand Down
10 changes: 5 additions & 5 deletions benchmarks/ops/bench_ada_layer_norm.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import torch
import torch.nn.functional as F

from benchmarks.benchmark_base import BenchmarkReport, ManifestBenchmark
from benchmarks.benchmark_base import BenchmarkReport, ManifestBenchmark, torch_inductor_baseline
from tileops.manifest import load_workloads
from tileops.ops.norm.ada_layer_norm import AdaLayerNormFwdOp
from tileops.ops.norm.ada_layer_norm_zero import AdaLayerNormZeroFwdOp
Expand Down Expand Up @@ -39,8 +39,8 @@ def baseline_fn(x, scale, shift):
normed = F.layer_norm(x, (n,), weight=None, bias=None, eps=test.eps)
return scale * normed + shift

result_bl = bm.profile(baseline_fn, *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch-ref")
result_bl = bm.profile(torch_inductor_baseline(baseline_fn), *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


@pytest.mark.parametrize("m, n, dtype", _to_params(load_workloads(_ADA_ZERO_OP_NAME)))
Expand All @@ -58,8 +58,8 @@ def baseline_fn(x, scale, shift, gate):
normed = F.layer_norm(x, (n,), weight=None, bias=None, eps=test.eps)
return gate * (scale * normed + shift)

result_bl = bm.profile(baseline_fn, *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch-ref")
result_bl = bm.profile(torch_inductor_baseline(baseline_fn), *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


if __name__ == "__main__":
Expand Down
15 changes: 10 additions & 5 deletions benchmarks/ops/bench_argreduce.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@
import pytest
import torch

from benchmarks.benchmark_base import BenchmarkReport, ManifestBenchmark, workloads_to_params
from benchmarks.benchmark_base import (
BenchmarkReport,
ManifestBenchmark,
torch_inductor_baseline,
workloads_to_params,
)
from tileops.ops.reduction.argreduce import ArgmaxFwdOp, ArgminFwdOp
from workloads.reduction import ArgmaxTest, ArgminTest

Expand Down Expand Up @@ -60,8 +65,8 @@ def test_argmax_bench(shape: tuple, dtype: torch.dtype, extra: dict) -> None:
def baseline_fn(x):
return x.argmax(dim=dim)

result_bl = bm.profile(baseline_fn, *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(baseline_fn), *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


# Argmin benchmarks
Expand Down Expand Up @@ -93,8 +98,8 @@ def test_argmin_bench(shape: tuple, dtype: torch.dtype, extra: dict) -> None:
def baseline_fn(x):
return x.argmin(dim=dim)

result_bl = bm.profile(baseline_fn, *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(baseline_fn), *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


if __name__ == "__main__":
Expand Down
4 changes: 2 additions & 2 deletions benchmarks/ops/bench_batch_norm.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def test_batch_norm_fwd_bench(N, C, spatial, dtype, training, tune):
result_bl = bm.profile(
lambda x, rm, rv, w, b: _torch_bn_fwd(x, w, b, rm, rv), *inputs,
)
BenchmarkReport.record(op, locals(), result_bl, tag="torch-cudnn")
BenchmarkReport.record(op, locals(), result_bl, tag="torch_cudnn")


@pytest.mark.parametrize("N, C, spatial, dtype", _manifest_bwd_params())
Expand All @@ -127,7 +127,7 @@ def test_batch_norm_bwd_bench(N, C, spatial, dtype):
BenchmarkReport.record(op, locals(), result, tag="tileops")

result_bl = bm.profile(_torch_bn_bwd, *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch-autograd")
BenchmarkReport.record(op, locals(), result_bl, tag="torch_cudnn")


if __name__ == "__main__":
Expand Down
36 changes: 22 additions & 14 deletions benchmarks/ops/bench_binary_elementwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
BenchmarkBase,
BenchmarkReport,
ManifestBenchmark,
torch_inductor_baseline,
)
from tileops.kernels.elementwise import (
GeluAndMulFwdKernel,
Expand Down Expand Up @@ -200,8 +201,8 @@ def test_binary_arith_bench(
result = bm.profile(op, *inputs)
BenchmarkReport.record(op, locals(), result, tag="tileops")

result_bl = bm.profile(baseline_fn, *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(baseline_fn), *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


# Comparison ops (6)
Expand Down Expand Up @@ -245,8 +246,8 @@ def test_comparison_bench(
result = bm.profile(op, *inputs)
BenchmarkReport.record(op, locals(), result, tag="tileops")

result_bl = bm.profile(baseline_fn, *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(baseline_fn), *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


# Logical ops (2)
Expand Down Expand Up @@ -281,8 +282,8 @@ def test_logical_bench(

# Baseline uses bool tensors
a_bool, b_bool = inputs[0].bool(), inputs[1].bool()
result_bl = bm.profile(baseline_fn, a_bool, b_bool)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(baseline_fn), a_bool, b_bool)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


# Bitwise ops (3)
Expand Down Expand Up @@ -315,8 +316,8 @@ def test_bitwise_bench(
result = bm.profile(op, *inputs)
BenchmarkReport.record(op, locals(), result, tag="tileops")

result_bl = bm.profile(baseline_fn, *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(baseline_fn), *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


# Fused gated ops (2)
Expand Down Expand Up @@ -380,8 +381,11 @@ def _profile_fused_gated(bm: ManifestBenchmark, op, test, baseline_key: str,
inputs = test.gen_inputs()
result = bm.profile(op, *inputs)
BenchmarkReport.record(op, params, result, tag="tileops")
result_bl = bm.profile(_FUSED_BASELINES[baseline_key], *inputs)
BenchmarkReport.record(op, params, result_bl, tag="torch-ref")
result_bl = bm.profile(
torch_inductor_baseline(_FUSED_BASELINES[baseline_key]),
*inputs,
)
BenchmarkReport.record(op, params, result_bl, tag="torch_inductor")


@SiluAndMulBenchFixture
Expand Down Expand Up @@ -475,8 +479,10 @@ def test_fused_gated_strategy_bench(
BenchmarkReport.record(f"{op_name}_strategy", locals(), result, tag=f"tileops-{strategy}")

baseline_fn = _FUSED_BASELINES[op_name]
result_bl = bm.profile(baseline_fn, *inputs)
BenchmarkReport.record(f"{op_name}_strategy", locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(baseline_fn), *inputs)
BenchmarkReport.record(
f"{op_name}_strategy", locals(), result_bl, tag="torch_inductor",
)


# Broadcast benchmark (bias-add pattern)
Expand Down Expand Up @@ -575,8 +581,10 @@ def test_broadcast_bench(
result = bm.profile(op, *inputs)
BenchmarkReport.record(f"{op_name}_bcast", locals(), result, tag="tileops")

result_bl = bm.profile(baseline_fn, *inputs)
BenchmarkReport.record(f"{op_name}_bcast", locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(baseline_fn), *inputs)
BenchmarkReport.record(
f"{op_name}_bcast", locals(), result_bl, tag="torch_inductor",
)


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/ops/bench_convolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def _profile_conv(
BenchmarkReport.record(op, params, result, tag="tileops")

result_bl = bm.profile(baseline_fn, *inputs)
BenchmarkReport.record(op, params, result_bl, tag="torch")
BenchmarkReport.record(op, params, result_bl, tag="torch_cudnn")


# Conv1d
Expand Down
9 changes: 5 additions & 4 deletions benchmarks/ops/bench_cumulative.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from benchmarks.benchmark_base import (
BenchmarkReport,
ManifestBenchmark,
torch_inductor_baseline,
workloads_to_params,
)
from workloads.workload_base import WorkloadBase
Expand Down Expand Up @@ -63,8 +64,8 @@ def test_cumsum_bench(shape: tuple, dtype: torch.dtype) -> None:
result = bm.profile(op, *inputs)
BenchmarkReport.record(op, locals(), result, tag="tileops")

result_bl = bm.profile(test.ref_program, *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(test.ref_program), *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


@pytest.mark.parametrize("shape, dtype", workloads_to_params(_CUMPROD_OP))
Expand All @@ -77,8 +78,8 @@ def test_cumprod_bench(shape: tuple, dtype: torch.dtype) -> None:
result = bm.profile(op, *inputs)
BenchmarkReport.record(op, locals(), result, tag="tileops")

result_bl = bm.profile(test.ref_program, *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(test.ref_program), *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


if __name__ == "__main__":
Expand Down
11 changes: 8 additions & 3 deletions benchmarks/ops/bench_dropout.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@
import torch
import torch.nn.functional as F

from benchmarks.benchmark_base import BenchmarkReport, ManifestBenchmark, workloads_to_params
from benchmarks.benchmark_base import (
BenchmarkReport,
ManifestBenchmark,
torch_inductor_baseline,
workloads_to_params,
)
from tileops.ops.dropout import DropoutOp
from workloads.workload_base import WorkloadBase

Expand Down Expand Up @@ -41,8 +46,8 @@ def test_dropout_bench(shape: tuple, dtype: torch.dtype) -> None:
result = bm.profile(op, x)
BenchmarkReport.record(op, locals(), result, tag="tileops")

result_bl = bm.profile(test.ref_program, x)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(test.ref_program), x)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


if __name__ == "__main__":
Expand Down
39 changes: 24 additions & 15 deletions benchmarks/ops/bench_elementwise_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import torch
import torch.nn.functional as F

from benchmarks.benchmark_base import BenchmarkReport, ManifestBenchmark
from benchmarks.benchmark_base import BenchmarkReport, ManifestBenchmark, torch_inductor_baseline
from tileops.manifest import load_workloads
from tileops.ops.elementwise import (
AddFwdOp,
Expand Down Expand Up @@ -362,8 +362,8 @@ def _record_unary(
) -> None:
result = bm.profile(op, *inputs)
BenchmarkReport.record(op, _manifest_params(bm), result, tag="tileops")
result_bl = bm.profile(baseline_fn, *inputs)
BenchmarkReport.record(op, _manifest_params(bm), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(baseline_fn), *inputs)
BenchmarkReport.record(op, _manifest_params(bm), result_bl, tag="torch_inductor")


def _record_binary(
Expand All @@ -374,8 +374,8 @@ def _record_binary(
) -> None:
result = bm.profile(op, *inputs)
BenchmarkReport.record(op, _manifest_params(bm), result, tag="tileops")
result_bl = bm.profile(baseline_fn, *inputs)
BenchmarkReport.record(op, _manifest_params(bm), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(baseline_fn), *inputs)
BenchmarkReport.record(op, _manifest_params(bm), result_bl, tag="torch_inductor")


_RELU_OP = "ReluFwdOp"
Expand Down Expand Up @@ -548,8 +548,8 @@ def test_prelu_manifest_bench(
bm = ManifestBenchmark(_PRELU_OP, op, test)
result = bm.profile(op, x, weight)
BenchmarkReport.record(op, locals(), result, tag="tileops")
result_bl = bm.profile(F.prelu, x, weight)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(F.prelu), x, weight)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


_MASKED_FILL_OP = "MaskedFillFwdOp"
Expand All @@ -572,8 +572,13 @@ def test_masked_fill_tensor_manifest_bench(
bm = ManifestBenchmark(_MASKED_FILL_OP, op, test)
result = bm.profile(op, x, mask, value)
BenchmarkReport.record(op, locals(), result, tag="tileops")
result_bl = bm.profile(lambda a, m, v: a.masked_fill(m, v), x, mask, value)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(
torch_inductor_baseline(lambda a, m, v: a.masked_fill(m, v)),
x,
mask,
value,
)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


@pytest.mark.parametrize(
Expand All @@ -590,8 +595,12 @@ def test_masked_fill_scalar_manifest_bench(
bm = ManifestBenchmark(_MASKED_FILL_SCALAR_OP, op, test)
result = bm.profile(op, x, mask)
BenchmarkReport.record(op, locals(), result, tag="tileops")
result_bl = bm.profile(lambda a, m: a.masked_fill(m, -100.0), x, mask)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(
torch_inductor_baseline(lambda a, m: a.masked_fill(m, -100.0)),
x,
mask,
)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


_ADD_OP = "AddFwdOp"
Expand Down Expand Up @@ -841,8 +850,8 @@ def test_where_manifest_bench(shape: tuple[int, ...], dtype: torch.dtype) -> Non
bm = ManifestBenchmark(_WHERE_OP, op, test)
result = bm.profile(op, cond, x, other)
BenchmarkReport.record(op, locals(), result, tag="tileops")
result_bl = bm.profile(torch.where, cond, x, other)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(torch.where), cond, x, other)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


@pytest.mark.parametrize("shape, dtype", _shape_dtype_params(load_workloads(_LERP_TENSOR_OP)))
Expand All @@ -853,8 +862,8 @@ def test_lerp_tensor_manifest_bench(shape: tuple[int, ...], dtype: torch.dtype)
bm = ManifestBenchmark(_LERP_TENSOR_OP, op, test)
result = bm.profile(op, x, end, weight)
BenchmarkReport.record(op, locals(), result, tag="tileops")
result_bl = bm.profile(torch.lerp, x, end, weight)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(torch.lerp), x, end, weight)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/ops/bench_fft.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def test_fft_bench(shape: tuple, dtype: torch.dtype) -> None:
BenchmarkReport.record(op, locals(), result, tag="tileops")

result_bl = bm.profile(test.ref_program, *inputs)
BenchmarkReport.record(op, locals(), result_bl, tag="torch-cufft")
BenchmarkReport.record(op, locals(), result_bl, tag="torch_cufft")


if __name__ == "__main__":
Expand Down
10 changes: 5 additions & 5 deletions benchmarks/ops/bench_group_norm.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import torch
import torch.nn.functional as F

from benchmarks.benchmark_base import BenchmarkReport, ManifestBenchmark
from benchmarks.benchmark_base import BenchmarkReport, ManifestBenchmark, torch_inductor_baseline
from tileops.manifest import load_workloads
from tileops.ops.norm.group_norm import (
GroupNormFwdOp,
Expand Down Expand Up @@ -52,8 +52,8 @@ def test_group_norm_bench(n: int, c: int, spatial: tuple, num_groups: int,
def baseline_fn(x, weight, bias):
return F.group_norm(x, num_groups, weight=weight, bias=bias, eps=1e-5)

result_bl = bm.profile(baseline_fn, x, weight, bias)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(baseline_fn), x, weight, bias)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


@pytest.mark.parametrize("n, c, spatial, num_groups, dtype, tune",
Expand All @@ -72,8 +72,8 @@ def test_group_norm_no_affine_bench(n: int, c: int, spatial: tuple,
def baseline_no_affine(x):
return F.group_norm(x, num_groups, weight=None, bias=None, eps=1e-5)

result_bl = bm.profile(baseline_no_affine, x)
BenchmarkReport.record(op, locals(), result_bl, tag="torch")
result_bl = bm.profile(torch_inductor_baseline(baseline_no_affine), x)
BenchmarkReport.record(op, locals(), result_bl, tag="torch_inductor")


if __name__ == "__main__":
Expand Down
Loading
Loading