Skip to content

Commit d89d74d

Browse files
authored
[KernelGen] Optimize mean on Ascend (#2162)
1 parent 4e7b7f8 commit d89d74d

2 files changed

Lines changed: 59 additions & 36 deletions

File tree

src/flag_gems/runtime/backend/_ascend/ops/mean.py

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,29 @@
1717
@triton.jit
1818
def mean_kernel_1(
1919
inp,
20-
out,
20+
mid,
2121
M,
2222
BLOCK_SIZE: tl.constexpr,
2323
):
2424
pid = tl.program_id(0)
2525
num_jobs = tl.num_programs(axis=0)
26-
block_start = pid * BLOCK_SIZE
27-
step = num_jobs * BLOCK_SIZE
28-
_tmp = tl.zeros([BLOCK_SIZE], dtype=tl.float32)
29-
block_start = block_start.to(tl.int64)
30-
for off in range(block_start, M, step):
26+
_sum = tl.zeros([BLOCK_SIZE], dtype=tl.float32)
27+
for off in range(pid * BLOCK_SIZE, M, num_jobs * BLOCK_SIZE):
3128
offset = off + tl.arange(0, BLOCK_SIZE)
3229
mask = offset < M
3330
inp_val = tl.load(inp + offset, mask=mask, other=0.0)
34-
_tmp = inp_val + _tmp
31+
_sum += inp_val.to(tl.float32)
32+
tl.store(mid + pid, tl.sum(_sum, axis=0))
3533

36-
mean_val = tl.sum(_tmp, axis=0) / M
37-
tl.atomic_add(out, mean_val)
34+
35+
@libentry()
36+
@triton.jit
37+
def mean_kernel_2(mid, out, M, MID_SIZE, BLOCK_MID: tl.constexpr):
38+
offset = tl.arange(0, BLOCK_MID)
39+
mask = offset < MID_SIZE
40+
mid_val = tl.load(mid + offset, mask=mask, other=0.0)
41+
mean_val = tl.sum(mid_val) / M
42+
tl.store(out, mean_val)
3843

3944

4045
def mean(inp, *, dtype=None):
@@ -43,12 +48,18 @@ def mean(inp, *, dtype=None):
4348
if dtype is None:
4449
dtype = inp.dtype
4550
block_size = triton.next_power_of_2(math.ceil(math.sqrt(M)))
46-
out = torch.zeros([], dtype=dtype, device=inp.device)
51+
block_size = min(block_size, 1024)
52+
mid_size = triton.cdiv(M, block_size)
53+
mid_size = min(mid_size, 4096)
54+
block_mid = triton.next_power_of_2(mid_size)
55+
56+
mid = torch.empty((mid_size,), dtype=torch.float32, device=inp.device)
57+
out = torch.empty([], dtype=torch.float32, device=inp.device)
4758

4859
with torch_device_fn.device(inp.device):
49-
mean_kernel_1[(triton.cdiv(M, block_size), 1, 1)](inp, out, M, block_size)
50-
# mean_kernel_2[(1, 1, 1)](mid, out, M, mid_size, block_mid)
51-
return out
60+
mean_kernel_1[(mid_size, 1, 1)](inp, mid, M, block_size)
61+
mean_kernel_2[(1, 1, 1)](mid, out, M, mid_size, block_mid)
62+
return out.to(dtype)
5263

5364

5465
@libentry()
@@ -58,24 +69,28 @@ def mean(inp, *, dtype=None):
5869
)
5970
@triton.jit
6071
def mean_dim_kernel(X, Mean, M, N, BLOCK_M: tl.constexpr, BLOCK_N: tl.constexpr):
61-
# Map the program id to the row of X it should compute.
62-
pid = tle.program_id(0) * BLOCK_M + tl.arange(0, BLOCK_M)[:, None]
63-
X = X + pid * N
64-
Mean = Mean + pid
65-
row_mask = pid < M
66-
67-
# Compute mean
68-
_mean = tl.zeros([BLOCK_M, BLOCK_N], dtype=tl.float32)
69-
for off in range(0, N, BLOCK_N):
70-
cols = off + tl.arange(0, BLOCK_N)[None, :]
71-
col_mask = cols < N
72-
mask = row_mask and col_mask
73-
74-
a = tl.load(X + cols, mask, other=0.0).to(tl.float32)
75-
_mean += a
76-
mean = tl.sum(_mean, axis=1) / N
77-
mean = mean[:, None]
78-
tl.store(Mean, mean, row_mask)
72+
workers = tle.num_programs(0)
73+
pid = tle.program_id(0)
74+
total_workloads = tl.cdiv(M, BLOCK_M)
75+
workloads = tl.cdiv(total_workloads, workers)
76+
77+
for w in range(workloads):
78+
work_id = pid + w * workers
79+
rows = work_id * BLOCK_M + tl.arange(0, BLOCK_M)[:, None]
80+
X_ptr = X + rows * N
81+
Mean_ptr = Mean + rows
82+
row_mask = rows < M
83+
84+
_mean = tl.zeros([BLOCK_M, BLOCK_N], dtype=tl.float32)
85+
for off in range(0, N, BLOCK_N):
86+
cols = off + tl.arange(0, BLOCK_N)[None, :]
87+
col_mask = cols < N
88+
mask = row_mask and col_mask
89+
a = tl.load(X_ptr + cols, mask, other=0.0).to(tl.float32)
90+
_mean += a
91+
mean = tl.sum(_mean, axis=1) / N
92+
mean = mean[:, None]
93+
tl.store(Mean_ptr, mean, row_mask)
7994

8095

8196
def mean_dim(x, dim, keepdim=False, *, dtype=None):
@@ -98,10 +113,14 @@ def mean_dim(x, dim, keepdim=False, *, dtype=None):
98113
shape[i] = 1
99114
M = x.numel() // N
100115
out = torch.empty(shape, dtype=dtype, device=x.device)
101-
grid = lambda META: (triton.cdiv(M, META["BLOCK_M"]),)
116+
117+
def grid(meta):
118+
axis0 = triton.cdiv(M, meta["BLOCK_M"])
119+
axis0 = axis0 if axis0 < 4096 else 4096
120+
return (axis0,)
102121

103122
with torch_device_fn.device(x.device):
104123
mean_dim_kernel[grid](x, out, M, N)
105124
if not keepdim:
106125
out = out.squeeze(dim)
107-
return out
126+
return out

src/flag_gems/runtime/backend/_ascend/tune_configs.yaml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,11 +306,15 @@ mean:
306306
param_map:
307307
META:
308308
BLOCK_M: block_m
309-
BLOCK_N: 256
309+
BLOCK_N: block_n
310310
block_m:
311+
- 1
312+
- 4
313+
- 8
314+
- 32
311315
- 64
312-
- 128
313-
- 256
316+
block_n:
317+
- 1024
314318

315319
instancenorm:
316320
- gen: true

0 commit comments

Comments
 (0)