Skip to content

Commit 514ce0f

Browse files
committed
resnet infer
1 parent 3a39afe commit 514ce0f

15 files changed

Lines changed: 1350 additions & 130 deletions

avg_pool2d.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
from contextlib import contextmanager
2+
import torch
3+
import torch.nn as nn
4+
import torch.nn.functional as F
5+
import triton
6+
7+
import ops.ninetoothed.torch
8+
import ops.triton.torch
9+
import ntops.torch
10+
11+
class AvgPool2d(nn.Module):
12+
avg_pool2d = None
13+
14+
def __init__(self, other):
15+
super().__init__()
16+
17+
self.__dict__ = other.__dict__
18+
19+
def forward(self, input):
20+
def _pair(x):
21+
return (x, x) if isinstance(x, int) else x
22+
23+
return type(self).avg_pool2d(
24+
input,
25+
kernel_size=_pair(self.kernel_size),
26+
stride=_pair(self.stride) if self.stride else _pair(self.kernel_size),
27+
padding=_pair(self.padding),
28+
ceil_mode=self.ceil_mode,
29+
count_include_pad=self.count_include_pad,
30+
divisor_override=self.divisor_override,
31+
)
32+
33+
34+
@contextmanager
35+
def avg_pool2d_backend(backend_name):
36+
_prev_impl = AvgPool2d.avg_pool2d
37+
38+
if backend_name == "ninetoothed":
39+
impl = ntops.torch.avg_pool2d
40+
elif backend_name == "triton":
41+
impl = ops.triton.torch.avg_pool2d
42+
elif backend_name == "torch":
43+
impl = F.avg_pool2d
44+
else:
45+
raise ValueError(f"unknown backend: `{backend_name}`")
46+
47+
AvgPool2d.avg_pool2d = impl
48+
49+
try:
50+
yield
51+
finally:
52+
AvgPool2d.avg_pool2d = _prev_impl
53+
54+
if __name__ == "__main__":
55+
torch.manual_seed(0)
56+
57+
input_shape = (32, 3, 64, 64)
58+
window_shape = (3, 3)
59+
60+
input = torch.randn(input_shape, dtype=torch.float16, device="cuda")
61+
62+
ninetoothed_output = ops.ninetoothed.torch.avg_pool2d(input, window_shape)
63+
torch_output = F.avg_pool2d(input, window_shape, ceil_mode=True)
64+
65+
print(ninetoothed_output)
66+
print(torch_output)
67+
68+
if torch.allclose(ninetoothed_output, torch_output):
69+
print("✅ NineToothed and PyTorch match.")
70+
else:
71+
print("❌ NineToothed and PyTorch differ.")
72+
73+
@triton.testing.perf_report(
74+
triton.testing.Benchmark(
75+
x_names=["h", "w"],
76+
x_vals=[8 * i for i in range(2, 33)],
77+
line_arg="provider",
78+
line_vals=["ninetoothed", "torch"],
79+
line_names=["NineToothed", "PyTorch"],
80+
styles=[("blue", "-"), ("green", "-")],
81+
ylabel="ms",
82+
plot_name="avg-pool2d-performance",
83+
args={},
84+
)
85+
)
86+
def benchmark(h, w, provider):
87+
n, c, h, w = 64, 64, h, w
88+
r, s = 3, 3
89+
dtype = torch.float16
90+
device = "cuda"
91+
input = torch.randn((n, c, h, w), dtype=dtype, device=device)
92+
window_shape = (r, s)
93+
94+
if provider == "ninetoothed":
95+
ms = triton.testing.do_bench(lambda: ops.ninetoothed.torch.avg_pool2d(input, window_shape))
96+
elif provider == "torch":
97+
ms = triton.testing.do_bench(lambda: F.avg_pool2d(input, window_shape))
98+
99+
return ms
100+
101+
benchmark.run(show_plots=True, print_data=True, save_path=".")

conv2d.py

Lines changed: 65 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,84 @@
1+
from contextlib import contextmanager
12
import torch
23
import torch.nn.functional as F
34
import triton
5+
import torch.nn as nn
46

57
import ops.ninetoothed.torch
68
import ops.triton.torch
9+
import ntops.torch
10+
11+
class Conv2d(nn.Module):
12+
conv2d = None
13+
14+
def __init__(self, other):
15+
super().__init__()
16+
17+
self.__dict__ = other.__dict__
18+
19+
def forward(self, input):
20+
def _pair(x):
21+
return x if isinstance(x, (tuple, list)) else (x, x)
22+
23+
stride = _pair(self.stride)
24+
padding = _pair(self.padding)
25+
dilation = _pair(self.dilation)
26+
27+
return type(self).conv2d(
28+
input,
29+
self.weight,
30+
self.bias,
31+
stride=stride,
32+
padding=padding,
33+
dilation=dilation,
34+
groups=self.groups,
35+
)
36+
37+
@contextmanager
38+
def conv2d_backend(backend_name):
39+
_prev_impl = Conv2d.conv2d
40+
if backend_name == "ninetoothed":
41+
impl = ntops.torch.conv2d
42+
elif backend_name == "torch":
43+
impl = F.conv2d
44+
else:
45+
raise ValueError(f"unknown backend: `{backend_name}`")
46+
47+
Conv2d.conv2d = impl
48+
49+
try:
50+
yield
51+
finally:
52+
Conv2d.conv2d = _prev_impl
753

854
if __name__ == "__main__":
955
torch.manual_seed(0)
1056

11-
n, c, h, w = 4, 3, 224, 224
12-
k, _, r, s = 8, c, 3, 3
57+
n, c, h, w = 2, 3, 112, 112
58+
k, _, r, s = 4, c, 3, 3
1359
dtype = torch.float16
1460
device = "cuda"
1561

16-
input = torch.randn(n, c, h, w, dtype=dtype, device=device)
17-
filter = torch.randn(k, c, r, s, dtype=dtype, device=device)
18-
19-
ninetoothed_output = ops.ninetoothed.torch.conv2d(input, filter)
20-
torch_output = F.conv2d(input, filter)
21-
triton_output = ops.triton.torch.conv2d(input, filter)
62+
input = torch.randn((n, c, h, w), dtype=dtype, device=device)
63+
weight = torch.randn((k, c, r, s), dtype=dtype, device=device)
64+
bias = torch.randn((k,), dtype=dtype, device=device)
65+
stride = 3
66+
dilation = 1
67+
68+
ninetoothed_output = ops.ninetoothed.torch.conv2d(
69+
input, weight, bias=bias, stride=stride, dilation=dilation
70+
)
71+
reference_output = F.conv2d(
72+
input, weight, bias=bias, stride=stride, dilation=dilation
73+
)
2274

75+
2376
print(ninetoothed_output)
24-
print(torch_output)
25-
print(triton_output)
77+
print(reference_output)
78+
2679

27-
if torch.allclose(ninetoothed_output, torch_output, atol=0.01, rtol=0.01):
80+
if torch.allclose(ninetoothed_output, reference_output, atol=0.01, rtol=0.01):
2881
print("✅ NineToothed and PyTorch match.")
2982
else:
3083
print("❌ NineToothed and PyTorch differ.")
31-
if torch.allclose(ninetoothed_output, triton_output, atol=0, rtol=0):
32-
print("✅ NineToothed and Triton match.")
33-
else:
34-
print("❌ NineToothed and Triton differ.")
35-
36-
@triton.testing.perf_report(
37-
triton.testing.Benchmark(
38-
x_names=["n"],
39-
x_vals=[2**i for i in range(1, 11)],
40-
x_log=True,
41-
line_arg="provider",
42-
line_vals=["ninetoothed", "torch", "triton"],
43-
line_names=["NineToothed", "PyTorch", "Triton"],
44-
styles=[("blue", "-"), ("green", "-"), ("orange", "-")],
45-
ylabel="ms",
46-
plot_name="conv2d-performance",
47-
args={},
48-
)
49-
)
50-
def benchmark(n, provider):
51-
_, c, h, w = n, 512, 14, 14
52-
k, _, r, s = 512, c, 3, 3
53-
54-
input = torch.randn((n, c, h, w), dtype=dtype, device=device)
55-
filter = torch.randn((k, c, r, s), dtype=dtype, device=device)
56-
57-
ninetoothed_output = ops.ninetoothed.torch.conv2d(input, filter)
58-
torch_output = F.conv2d(input, filter)
59-
triton_output = ops.triton.torch.conv2d(input, filter)
60-
61-
assert torch.allclose(ninetoothed_output, torch_output, atol=0.01, rtol=0.01)
62-
assert torch.allclose(ninetoothed_output, triton_output, atol=0, rtol=0)
63-
64-
if provider == "ninetoothed":
65-
ms = triton.testing.do_bench(
66-
lambda: ops.ninetoothed.torch.conv2d(input, filter)
67-
)
68-
elif provider == "torch":
69-
ms = triton.testing.do_bench(lambda: F.conv2d(input, filter))
70-
elif provider == "triton":
71-
ms = triton.testing.do_bench(lambda: ops.triton.torch.conv2d(input, filter))
72-
73-
return ms
74-
75-
benchmark.run(show_plots=True, print_data=True, save_path=".")
84+

max_pool2d.py

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,79 @@
1-
import math
2-
3-
import ninetoothed
4-
import ninetoothed.language as ntl
1+
from contextlib import contextmanager
52
import torch
3+
import torch.nn as nn
64
import torch.nn.functional as F
75
import triton
8-
from ninetoothed import Symbol, Tensor
9-
10-
11-
def arrangement(input, output):
12-
BLOCK_SIZE = Symbol("BLOCK_SIZE", meta=True)
13-
14-
WINDOW_HEIGHT = Symbol("WINDOW_HEIGHT", constexpr=True, upper_bound=16)
15-
WINDOW_WIDTH = Symbol("WINDOW_WIDTH", constexpr=True, upper_bound=16)
16-
17-
input_arranged = input.tile((1, 1, WINDOW_HEIGHT, WINDOW_WIDTH))
18-
input_arranged = input_arranged.ravel()
19-
input_arranged = input_arranged.flatten(end_dim=4).flatten(start_dim=1)
20-
input_arranged = input_arranged.tile((BLOCK_SIZE, -1))
21-
22-
output_arranged = output.tile((1, 1, 1, 1))
23-
output_arranged = output_arranged.ravel()
24-
output_arranged = output_arranged.flatten(end_dim=4).flatten(start_dim=1)
25-
output_arranged = output_arranged.tile((BLOCK_SIZE, -1))
26-
output_arranged.dtype = output_arranged.dtype.squeeze(1)
27-
28-
return input_arranged, output_arranged
29-
30-
31-
def application(input, output):
32-
output = ntl.max(input, axis=1) # noqa: F841
33-
34-
35-
max_pool2d_kernel = ninetoothed.make(
36-
arrangement, application, (Tensor(4, other=float("-inf")), Tensor(4))
37-
)
386

7+
import ops.ninetoothed.torch
8+
import ops.triton.torch
9+
10+
import ntops.torch
11+
12+
class MaxPool2d(nn.Module):
13+
max_pool2d = None
14+
15+
def __init__(self, other):
16+
super().__init__()
17+
18+
self.__dict__ = other.__dict__
19+
20+
# def forward(self, input):
21+
# print("using ninetoothed max_pool2d kernel")
22+
# return type(self).max_pool2d(input)
23+
def forward(self, input):
24+
25+
# 处理 kernel_size(确保是 tuple)
26+
kernel_size = self.kernel_size
27+
if isinstance(kernel_size, int):
28+
kernel_size = (kernel_size, kernel_size)
29+
30+
# 处理 stride(None 表示默认等于 kernel_size)
31+
stride = self.stride
32+
if stride is None:
33+
stride = kernel_size
34+
elif isinstance(stride, int):
35+
stride = (stride, stride)
36+
37+
# 处理 padding
38+
padding = self.padding
39+
if isinstance(padding, int):
40+
padding = (padding, padding)
41+
42+
# 处理 dilation
43+
dilation = self.dilation
44+
if isinstance(dilation, int):
45+
dilation = (dilation, dilation)
46+
47+
return type(self).max_pool2d(
48+
input,
49+
kernel_size=kernel_size,
50+
stride=stride,
51+
padding=padding,
52+
dilation=dilation,
53+
ceil_mode=self.ceil_mode,
54+
return_indices=self.return_indices,
55+
)
3956

40-
def max_pool2d(input, window_shape):
41-
n, c, h, w = input.shape
42-
r, s = window_shape
43-
p = math.ceil((h - r) / r + 1)
44-
q = math.ceil((w - s) / s + 1)
4557

46-
output = torch.empty(n, c, p, q, dtype=input.dtype, device=input.device)
58+
@contextmanager
59+
def max_pool2d_backend(backend_name):
60+
_prev_impl = MaxPool2d.max_pool2d
4761

48-
max_pool2d_kernel(input, output, WINDOW_HEIGHT=r, WINDOW_WIDTH=s)
62+
if backend_name == "ninetoothed":
63+
impl = ntops.torch.max_pool2d
64+
elif backend_name == "triton":
65+
impl = ops.triton.torch.max_pool2d
66+
elif backend_name == "torch":
67+
impl = F.max_pool2d
68+
else:
69+
raise ValueError(f"unknown backend: `{backend_name}`")
4970

50-
return output
71+
MaxPool2d.max_pool2d = impl
5172

73+
try:
74+
yield
75+
finally:
76+
MaxPool2d.max_pool2d = _prev_impl
5277

5378
if __name__ == "__main__":
5479
torch.manual_seed(0)
@@ -58,7 +83,7 @@ def max_pool2d(input, window_shape):
5883

5984
input = torch.randn(input_shape, dtype=torch.float16, device="cuda")
6085

61-
ninetoothed_output = max_pool2d(input, window_shape)
86+
ninetoothed_output = ops.ninetoothed.torch.max_pool2d(input, window_shape)
6287
torch_output = F.max_pool2d(input, window_shape, ceil_mode=True)
6388

6489
print(ninetoothed_output)
@@ -91,7 +116,7 @@ def benchmark(h, w, provider):
91116
window_shape = (r, s)
92117

93118
if provider == "ninetoothed":
94-
ms = triton.testing.do_bench(lambda: max_pool2d(input, window_shape))
119+
ms = triton.testing.do_bench(lambda: ops.ninetoothed.torch.max_pool2d(input, window_shape))
95120
elif provider == "torch":
96121
ms = triton.testing.do_bench(lambda: F.max_pool2d(input, window_shape))
97122

0 commit comments

Comments
 (0)