Skip to content

Commit 8878595

Browse files
committed
Migrate more kernels to ninetoothed.build
1 parent 57a42a4 commit 8878595

5 files changed

Lines changed: 362 additions & 34 deletions

File tree

ops/ninetoothed/kernels/addmm.py

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1+
import functools
2+
13
import ninetoothed
24
from ninetoothed import Tensor
35

46
import ops.ninetoothed.kernels.mm as mm
7+
from ops.ninetoothed.kernels._common import build
58

69

7-
def arrangement(input, mat1, mat2, beta, alpha, output):
8-
_, _, input_arranged = mm.arrangement(mat1, mat2, input)
9-
10-
mat1_arranged, mat2_arranged, output_arranged = mm.arrangement(mat1, mat2, output)
10+
def arrangement(input, mat1, mat2, beta, alpha, output, **block_sizes):
11+
_, _, input_arranged = mm.arrangement(mat1, mat2, input, **block_sizes)
12+
mat1_arranged, mat2_arranged, output_arranged = mm.arrangement(
13+
mat1, mat2, output, **block_sizes
14+
)
1115

1216
return input_arranged, mat1_arranged, mat2_arranged, beta, alpha, output_arranged
1317

@@ -17,6 +21,76 @@ def application(input, mat1, mat2, beta, alpha, output):
1721
output = beta * input + alpha * output
1822

1923

20-
tensors = (Tensor(2), Tensor(2), Tensor(2), Tensor(0), Tensor(0), Tensor(2))
24+
def premake(m, n, k, dtype, block_size_m, block_size_n, block_size_k):
25+
arrangement_ = functools.partial(
26+
arrangement,
27+
block_size_m=block_size_m,
28+
block_size_n=block_size_n,
29+
block_size_k=block_size_k,
30+
)
31+
tensors = (
32+
Tensor(shape=(m, n), dtype=dtype),
33+
Tensor(shape=(m, k), dtype=dtype),
34+
Tensor(shape=(k, n), dtype=dtype),
35+
Tensor(0, dtype=ninetoothed.float32),
36+
Tensor(0, dtype=ninetoothed.float32),
37+
Tensor(shape=(m, n), dtype=dtype),
38+
)
39+
40+
return arrangement_, application, tensors
41+
42+
43+
# Compile the square shapes used by the benchmark; other shapes use the generic
44+
# make-based fallback below.
45+
configs = tuple(
46+
(
47+
(),
48+
{
49+
"m": s,
50+
"n": s,
51+
"k": s,
52+
"dtype": ninetoothed.float16,
53+
"block_size_m": bm,
54+
"block_size_n": bn,
55+
"block_size_k": bk,
56+
},
57+
{"num_warps": nw, "num_stages": 3},
58+
)
59+
for s in (128 * i for i in range(2, 33))
60+
for bm in (64, 128)
61+
for bn in (64, 128)
62+
for bk in (32, 64)
63+
for nw in (4, 8)
64+
)
65+
66+
_build_kernel = build(
67+
premake,
68+
configs,
69+
meta_parameters=("block_size_m", "block_size_n", "block_size_k"),
70+
kernel_name="addmm",
71+
)
72+
73+
_BUILD_CONFIGS = frozenset(
74+
(kwargs["m"], kwargs["n"], kwargs["k"], kwargs["dtype"])
75+
for _, kwargs, _ in configs
76+
)
77+
78+
_fallback_kernel = ninetoothed.make(
79+
arrangement,
80+
application,
81+
(
82+
Tensor(2),
83+
Tensor(2),
84+
Tensor(2),
85+
Tensor(0),
86+
Tensor(0),
87+
Tensor(2),
88+
),
89+
)
90+
91+
92+
def kernel(input, mat1, mat2, beta, alpha, output, m, n, k, dtype):
93+
if (m, n, k, dtype) in _BUILD_CONFIGS:
94+
return _build_kernel(input, mat1, mat2, beta, alpha, output, m, n, k, dtype)
2195

22-
kernel = ninetoothed.make(arrangement, application, tensors)
96+
return _fallback_kernel(input, mat1, mat2, beta, alpha, output)

ops/ninetoothed/kernels/conv2d.py

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import functools
2+
13
import ninetoothed
24
from ninetoothed import Tensor
35

46
import ops.ninetoothed.kernels.mm as mm
7+
from ops.ninetoothed.kernels._common import build
58

69

7-
def arrangement(input, filter, output):
10+
def arrangement(input, filter, output, **block_sizes):
811
input_arranged = input.tile((1, *filter.shape[1:]), strides=(-1, -1, 1, 1))
912
input_arranged = input_arranged.squeeze(1)
1013
input_arranged.dtype = input_arranged.dtype.squeeze(0)
@@ -16,10 +19,90 @@ def arrangement(input, filter, output):
1619

1720
output_arranged = output.permute((0, 2, 3, 1)).flatten(end_dim=3)
1821

19-
return mm.arrangement(input_arranged, filter_arranged, output_arranged)
22+
return mm.arrangement(
23+
input_arranged, filter_arranged, output_arranged, **block_sizes
24+
)
25+
26+
27+
def premake(n, c, h, w, k, r, s, dtype, block_size_m, block_size_n, block_size_k):
28+
arrangement_ = functools.partial(
29+
arrangement,
30+
block_size_m=block_size_m,
31+
block_size_n=block_size_n,
32+
block_size_k=block_size_k,
33+
)
34+
35+
p = h - r + 1
36+
q = w - s + 1
37+
38+
tensors = (
39+
Tensor(shape=(n, c, h, w), dtype=dtype),
40+
Tensor(shape=(k, c, r, s), dtype=dtype),
41+
Tensor(shape=(n, k, p, q), dtype=dtype),
42+
)
43+
44+
return arrangement_, mm.application, tensors
45+
46+
47+
# Block sweep approximating the JIT auto-tuner default range. Conv2d's im2col
48+
# arrangement produces a tall-skinny matmul, so wider bn (up to 256) and
49+
# longer-pipelined num_stages help match the JIT-tuned kernel.
50+
configs = tuple(
51+
(
52+
(),
53+
{
54+
"n": n,
55+
"c": 512,
56+
"h": 14,
57+
"w": 14,
58+
"k": 512,
59+
"r": 3,
60+
"s": 3,
61+
"dtype": ninetoothed.float16,
62+
"block_size_m": bm,
63+
"block_size_n": bn,
64+
"block_size_k": bk,
65+
},
66+
{"num_warps": 8, "num_stages": ns},
67+
)
68+
for n in (2, 4, 8, 16, 32, 64, 128, 256, 512, 1024)
69+
for bm in (64, 128)
70+
for bn in (128, 256)
71+
for bk in (32, 64)
72+
for ns in (3, 5)
73+
if bm * bn <= 32768 and bm * bk <= 32768 and bn * bk <= 32768
74+
)
75+
76+
_build_kernel = build(
77+
premake,
78+
configs,
79+
meta_parameters=("block_size_m", "block_size_n", "block_size_k"),
80+
kernel_name="conv2d",
81+
)
82+
83+
_BUILD_CONFIGS = frozenset(
84+
(
85+
kwargs["n"],
86+
kwargs["c"],
87+
kwargs["h"],
88+
kwargs["w"],
89+
kwargs["k"],
90+
kwargs["r"],
91+
kwargs["s"],
92+
kwargs["dtype"],
93+
)
94+
for _, kwargs, _ in configs
95+
)
96+
97+
_fallback_kernel = ninetoothed.make(
98+
arrangement,
99+
mm.application,
100+
tuple(Tensor(4, shape_options={"constexpr": True}) for _ in range(3)),
101+
)
20102

21103

22-
shape_options = {"constexpr": True}
23-
tensors = tuple(Tensor(4, shape_options=shape_options) for _ in range(3))
104+
def kernel(input, filter, output, n, c, h, w, k, r, s, dtype):
105+
if (n, c, h, w, k, r, s, dtype) in _BUILD_CONFIGS:
106+
return _build_kernel(input, filter, output, n, c, h, w, k, r, s, dtype)
24107

25-
kernel = ninetoothed.make(arrangement, mm.application, tensors)
108+
return _fallback_kernel(input, filter, output)

ops/ninetoothed/kernels/max_pool2d.py

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
1+
import functools
2+
13
import ninetoothed
24
import ninetoothed.language as ntl
3-
from ninetoothed import Symbol, Tensor
5+
from ninetoothed import Symbol, Tensor, block_size
46

5-
BLOCK_SIZE = Symbol("BLOCK_SIZE", meta=True)
7+
from ops.ninetoothed.kernels._common import build
68

7-
WINDOW_HEIGHT = Symbol("WINDOW_HEIGHT", constexpr=True, upper_bound=16)
8-
WINDOW_WIDTH = Symbol("WINDOW_WIDTH", constexpr=True, upper_bound=16)
9+
BLOCK_SIZE = block_size()
910

1011

11-
def arrangement(input, output):
12-
input_arranged = input.tile((1, 1, WINDOW_HEIGHT, WINDOW_WIDTH))
12+
def arrangement(
13+
input,
14+
output,
15+
window_height,
16+
window_width,
17+
BLOCK_SIZE=BLOCK_SIZE,
18+
):
19+
input_arranged = input.tile((1, 1, window_height, window_width))
1320
input_arranged = input_arranged.ravel()
1421
input_arranged = input_arranged.flatten(end_dim=4).flatten(start_dim=1)
1522
input_arranged = input_arranged.tile((BLOCK_SIZE, -1))
@@ -27,6 +34,76 @@ def application(input, output):
2734
output = ntl.max(input, axis=1) # noqa: F841
2835

2936

30-
kernel = ninetoothed.make(
31-
arrangement, application, (Tensor(4, other=float("-inf")), Tensor(4))
37+
def premake(window_height, window_width, dtype, block_size_):
38+
arrangement_ = functools.partial(
39+
arrangement,
40+
window_height=window_height,
41+
window_width=window_width,
42+
BLOCK_SIZE=block_size_,
43+
)
44+
tensors = (
45+
Tensor(4, dtype=dtype, other=float("-inf")),
46+
Tensor(4, dtype=dtype),
47+
)
48+
49+
return arrangement_, application, tensors
50+
51+
52+
# Compile the benchmarked 3x3 fp16 case; other windows and dtypes use the
53+
# generic make-based fallback below.
54+
configs = (
55+
(
56+
(),
57+
{
58+
"window_height": 3,
59+
"window_width": 3,
60+
"dtype": ninetoothed.float16,
61+
"block_size_": 256,
62+
},
63+
{},
64+
),
65+
)
66+
67+
_build_kernel = build(
68+
premake,
69+
configs,
70+
meta_parameters=("block_size_",),
71+
kernel_name="max_pool2d",
72+
)
73+
74+
_BUILD_CONFIGS = frozenset(
75+
(kwargs["window_height"], kwargs["window_width"], kwargs["dtype"])
76+
for _, kwargs, _ in configs
77+
)
78+
79+
_FALLBACK_BLOCK_SIZE = block_size()
80+
_FALLBACK_WINDOW_HEIGHT = Symbol(
81+
"FALLBACK_WINDOW_HEIGHT", constexpr=True, upper_bound=16
3282
)
83+
_FALLBACK_WINDOW_WIDTH = Symbol("FALLBACK_WINDOW_WIDTH", constexpr=True, upper_bound=16)
84+
85+
86+
def _fallback_arrangement(
87+
input,
88+
output,
89+
BLOCK_SIZE=_FALLBACK_BLOCK_SIZE,
90+
WINDOW_HEIGHT=_FALLBACK_WINDOW_HEIGHT,
91+
WINDOW_WIDTH=_FALLBACK_WINDOW_WIDTH,
92+
):
93+
return arrangement(input, output, WINDOW_HEIGHT, WINDOW_WIDTH, BLOCK_SIZE)
94+
95+
96+
_fallback_kernel = ninetoothed.make(
97+
_fallback_arrangement,
98+
application,
99+
(Tensor(4, other=float("-inf")), Tensor(4)),
100+
)
101+
102+
103+
def kernel(input, output, window_height, window_width, dtype):
104+
if (window_height, window_width, dtype) in _BUILD_CONFIGS:
105+
return _build_kernel(input, output, window_height, window_width, dtype)
106+
107+
return _fallback_kernel(
108+
input, output, WINDOW_HEIGHT=window_height, WINDOW_WIDTH=window_width
109+
)

0 commit comments

Comments
 (0)