Skip to content

Commit 16cf752

Browse files
committed
cambricon: cambricon merge to master
1 parent 1a679d2 commit 16cf752

72 files changed

Lines changed: 2015 additions & 1192 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

benchmark/test_special_perf.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def isin_input_fn(shape, dtype, device):
9292
input_fn=isin_input_fn,
9393
op_name="isin",
9494
torch_op=torch.isin,
95-
dtypes=[torch.int32] if vendor_name == "cambricon" else INT_DTYPES,
95+
dtypes=INT_DTYPES,
9696
)
9797
bench.run()
9898

@@ -108,7 +108,7 @@ def unique_input_fn(shape, dtype, device):
108108
input_fn=unique_input_fn,
109109
op_name="unique",
110110
torch_op=torch.unique,
111-
dtypes=[torch.int32] if vendor_name == "cambricon" else INT_DTYPES,
111+
dtypes=INT_DTYPES,
112112
)
113113
bench.run()
114114

@@ -400,6 +400,7 @@ def diagonal_backward_input_fn(shape, dtype, device):
400400

401401
@pytest.mark.skipif(flag_gems.device == "musa", reason="ZeroDivisionError")
402402
@pytest.mark.skipif(vendor_name == "kunlunxin", reason="RESULT TODOFIX")
403+
@pytest.mark.skipif(vendor_name == "cambricon", reason="TODOFIX")
403404
@pytest.mark.kron
404405
def test_perf_kron():
405406
class KronBenchmark(GenericBenchmark2DOnly):
@@ -428,8 +429,8 @@ def contiguous_input_fn(shape, dtype, device):
428429
inp = torch.randn(shape, dtype=dtype, device=device)
429430
else:
430431
inp = torch.randint(
431-
low=-10000, high=10000, size=shape, dtype=dtype, device=device
432-
)
432+
low=-10000, high=10000, size=shape, dtype=dtype, device="cpu"
433+
).to(device)
433434
inp = inp[::2]
434435
yield inp,
435436

benchmark/test_unary_pointwise_perf.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
)
1515
from .performance_utils import Benchmark, generate_tensor_input
1616

17+
fp64_is_supported = flag_gems.runtime.device.support_fp64
18+
1719

1820
class UnaryPointwiseBenchmark(Benchmark):
1921
"""
@@ -136,7 +138,8 @@ def test_to_dtype_perf():
136138
bench = ToDtypeBenchmark(
137139
op_name="to",
138140
torch_op=torch.Tensor.to,
139-
dtypes=[torch.float16, torch.bfloat16, torch.float64],
141+
dtypes=[torch.float16, torch.bfloat16]
142+
+ ([torch.float64] if fp64_is_supported else []),
140143
)
141144
bench.run()
142145

src/flag_gems/runtime/backend/_cambricon/__init__.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@
2929
"sort", # skip now
3030
"multinomial", # skip now
3131
"_upsample_bicubic2d_aa", # skip now
32-
"batch_norm", #
33-
"pad",
34-
"constant_pad_nd", #
3532
)
3633

3734
__all__ = ["*"]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1+
from .cross_entropy_loss import cross_entropy_loss
12
from .fused_add_rms_norm import fused_add_rms_norm
23
from .gelu_and_mul import gelu_and_mul
4+
from .outer import outer
35
from .silu_and_mul import silu_and_mul
46
from .skip_layernorm import skip_layer_norm
7+
from .weight_norm import weight_norm
58

69
__all__ = [
710
"skip_layer_norm",
811
"fused_add_rms_norm",
912
"silu_and_mul",
1013
"gelu_and_mul",
14+
"cross_entropy_loss",
15+
"outer",
16+
"weight_norm",
1117
]

src/flag_gems/runtime/backend/_cambricon/ops/cross_entropy_loss.py renamed to src/flag_gems/runtime/backend/_cambricon/fused/cross_entropy_loss.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
import torch
44
import triton
55
import triton.language as tl
6+
from torch.nn import _reduction as _Reduction
67

78
from flag_gems import runtime
89
from flag_gems.runtime import torch_device_fn
910
from flag_gems.utils import libentry
1011

12+
from ..ops import sum
1113
from ..utils import TOTAL_CORE_NUM
12-
from .sum import sum
1314

1415
logger = logging.getLogger(__name__)
1516

@@ -999,8 +1000,13 @@ def backward(ctx, out_grad):
9991000

10001001

10011002
def cross_entropy_loss(
1002-
inp, target, weight=None, reduction=1, ignore_index=-100, label_smoothing=0.0
1003+
inp, target, weight=None, reduction="mean", ignore_index=-100, label_smoothing=0.0
10031004
):
10041005
return CrossEntropyLoss.apply(
1005-
inp, target, weight, reduction, ignore_index, label_smoothing
1006+
inp,
1007+
target,
1008+
weight,
1009+
_Reduction.get_enum(reduction),
1010+
ignore_index,
1011+
label_smoothing,
10061012
)

src/flag_gems/runtime/backend/_cambricon/fused/fused_add_rms_norm.py

Lines changed: 25 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def get_configs():
3030
@triton.autotune(
3131
configs=get_configs(),
3232
key=["M", "N_COLS"],
33+
restore_value=["x_ptr", "r_ptr"],
3334
)
3435
@libentry()
3536
@triton.jit(do_not_specialize=["eps"])
@@ -57,52 +58,37 @@ def fused_add_rms_norm_kernel(
5758
_mean = tl.zeros([M_BLOCK, BLOCK_SIZE], dtype=tl.float32)
5859
for offset in range(0, N_COLS, BLOCK_SIZE):
5960
cols = offset + tl.arange(0, BLOCK_SIZE)
60-
mask = (m_offset < M)[:, None] & (cols < N_COLS)[None, :]
61-
x = tl.load(
62-
mx_ptr[:, None] + cols[None, :],
63-
mask=mask,
64-
other=0.0,
65-
eviction_policy="evict_last",
66-
).to(tl.float32)
67-
r = tl.load(
68-
mr_ptr[:, None] + cols[None, :],
69-
mask=mask,
70-
other=0.0,
71-
eviction_policy="evict_last",
72-
).to(tl.float32)
73-
x += r
74-
_mean += x * x
61+
row_mask = m_offset < ub
62+
col_mask = cols < N_COLS
63+
mask = row_mask[:, None] & col_mask[None, :]
64+
x = tl.load(mx_ptr[:, None] + cols[None, :], mask=mask, other=0.0).to(
65+
tl.float32
66+
)
67+
r = tl.load(mr_ptr[:, None] + cols[None, :], mask=mask, other=0.0).to(
68+
tl.float32
69+
)
70+
xpr = x + r
71+
tl.store(mr_ptr[:, None] + cols[None, :], xpr, mask=mask)
72+
_mean += xpr * xpr
7573

7674
# Since `_mean * (1 / N_COLS)` performs better, make this change.
7775
# var = tl.sum(_mean / N_COLS, axis=1)
78-
var = tl.sum(_mean * (1 / N_COLS), axis=1)
79-
rrms = 1 / tl.sqrt(var + eps)
76+
var = tl.sum(_mean * (1.0 / N_COLS), axis=1)
77+
rrms = 1.0 / tl.sqrt(var + eps)
8078

8179
for offset in range(0, N_COLS, BLOCK_SIZE):
8280
cols = offset + tl.arange(0, BLOCK_SIZE)
83-
mask = (m_offset < M)[:, None] & (cols < N_COLS)[None, :]
84-
x = tl.load(
85-
mx_ptr[:, None] + cols[None, :],
86-
mask=mask,
87-
other=0.0,
88-
eviction_policy="evict_first",
89-
).to(tl.float32)
90-
r = tl.load(
91-
mr_ptr[:, None] + cols[None, :],
92-
mask=mask,
93-
other=0.0,
94-
eviction_policy="evict_last",
95-
).to(tl.float32)
96-
x += r
97-
w = tl.load(
98-
w_ptr + cols,
99-
mask=cols < N_COLS,
100-
other=0.0,
101-
eviction_policy="evict_first",
81+
row_mask = m_offset < ub
82+
col_mask = cols < N_COLS
83+
mask = row_mask[:, None] & col_mask[None, :]
84+
85+
xpr = tl.load(mr_ptr[:, None] + cols[None, :], mask=mask, other=0.0).to(
86+
tl.float32
10287
)
103-
y = (x * rrms[:, None]).to(x_ptr.dtype.element_ty) * w
104-
# write back to residual and input
105-
tl.store(mr_ptr[:, None] + cols[None, :], x, mask=mask)
88+
w = tl.load(w_ptr + cols, mask=col_mask, other=0.0).to(tl.float32)
89+
y = xpr * rrms[:, None]
90+
y = y * w
91+
y = y.to(x_ptr.dtype.element_ty)
10692
tl.store(mx_ptr[:, None] + cols[None, :], y, mask=mask)
10793

10894

src/flag_gems/runtime/backend/_cambricon/fused/gelu_and_mul.py

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,33 @@ def gelu_none_and_mul_kernel(x, y):
2121
return x_gelu * y
2222

2323

24+
@pointwise_dynamic(
25+
promotion_methods=[(0, 1, 2, "DEFAULT"), (0, 1, 2, "DEFAULT")], num_outputs=2
26+
)
27+
@triton.jit
28+
def gelu_none_and_mul_grad_kernel(x, y, dgrad):
29+
RCP_SQRT_2: tl.constexpr = 0.7071067811
30+
COEFF: tl.constexpr = 0.7978845608028654
31+
32+
x_fp32 = x.to(tl.float32)
33+
x_gelu = 0.5 * x_fp32 * (1 + fast_erf(x_fp32 * RCP_SQRT_2))
34+
35+
d_gelu = dgrad * y
36+
dx = (
37+
d_gelu
38+
* 0.5
39+
* (
40+
1.0
41+
+ fast_erf(x_fp32 * RCP_SQRT_2)
42+
+ x_fp32 * COEFF * tl.exp(-0.5 * x_fp32 * x_fp32)
43+
)
44+
)
45+
46+
dy = dgrad * x_gelu
47+
48+
return dx, dy
49+
50+
2451
@pointwise_dynamic(promotion_methods=[(0, 1, "DEFAULT")])
2552
@triton.jit
2653
def gelu_tanh_and_mul_kernel(x, y):
@@ -33,17 +60,57 @@ def gelu_tanh_and_mul_kernel(x, y):
3360
return x_gelu * y
3461

3562

63+
@pointwise_dynamic(
64+
promotion_methods=[(0, 1, 2, "DEFAULT"), (0, 1, 2, "DEFAULT")], num_outputs=2
65+
)
66+
@triton.jit
67+
def gelu_tanh_and_mul_grad_kernel(x, y, dgrad):
68+
x_fp32 = x.to(tl.float32)
69+
y_fp32 = y.to(tl.float32)
70+
71+
sqrt_2_over_pi = 0.7978845608028654 # sqrt(2 / pi)
72+
a_cubed = x_fp32 * x_fp32 * x_fp32
73+
tanh_arg = sqrt_2_over_pi * (x_fp32 + 0.044715 * a_cubed)
74+
tanh_result = fast_tanh(tanh_arg)
75+
geglu_a = 0.5 * x_fp32 * (1 + tanh_result)
76+
dy = geglu_a * dgrad
77+
78+
term1 = 0.5 * (1 + tanh_result)
79+
tanh_sq = tanh_result * tanh_result
80+
term2 = (
81+
0.5
82+
* x_fp32
83+
* (1 - tanh_sq)
84+
* (sqrt_2_over_pi * (1 + 3 * 0.044715 * x_fp32 * x_fp32))
85+
)
86+
dx = dgrad * y_fp32 * (term1 + term2)
87+
88+
return dx, dy
89+
90+
3691
class GeluAndMul(torch.autograd.Function):
3792
@staticmethod
38-
def forward(ctx, A, B, approximate="none"):
93+
def forward(ctx, x, y, approximate="none"):
3994
logger.debug("GEMS_CAMBRICON GELU AND MUL FORWARD")
95+
ctx.save_for_backward(x, y)
96+
ctx.approximate = approximate
4097
if approximate == "none":
41-
return gelu_none_and_mul_kernel(A, B)
98+
return gelu_none_and_mul_kernel(x, y)
4299
elif approximate == "tanh":
43-
return gelu_tanh_and_mul_kernel(A, B)
100+
return gelu_tanh_and_mul_kernel(x, y)
44101
else:
45102
raise ValueError(f"Invalid approximate value: {approximate}")
46103

104+
@staticmethod
105+
def backward(ctx, dgrad):
106+
logging.debug("GEMS GELU AND MUL BACKWARD")
107+
x, y = ctx.saved_tensors
108+
if ctx.approximate == "none":
109+
dx, dy = gelu_none_and_mul_grad_kernel(x, y, dgrad)
110+
else:
111+
dx, dy = gelu_tanh_and_mul_grad_kernel(x, y, dgrad)
112+
return dx, dy, None
113+
47114

48115
def gelu_and_mul(A, B, approximate="none"):
49116
return GeluAndMul.apply(A, B, approximate)

src/flag_gems/runtime/backend/_cambricon/ops/outer.py renamed to src/flag_gems/runtime/backend/_cambricon/fused/outer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
from flag_gems.utils import libentry
88

9+
from ..ops import mv
910
from ..utils import TOTAL_CORE_NUM
10-
from .mv import mv
1111

1212
logger = logging.getLogger(__name__)
1313

src/flag_gems/runtime/backend/_cambricon/fused/silu_and_mul.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,32 @@ def silu_and_mul_kernel(x, y):
1717
return x_silu * y
1818

1919

20+
@pointwise_dynamic(
21+
promotion_methods=[(0, 1, 2, "DEFAULT"), (0, 1, 2, "DEFAULT")], num_outputs=2
22+
)
23+
@triton.jit
24+
def silu_and_mul_grad_kernel(x, y, dgrad):
25+
x_fp32 = x.to(tl.float32)
26+
sig = tl.extra.mlu.libdevice.fast_sigmoid(x_fp32)
27+
x_silu = x_fp32 * sig
28+
d_x_silu = sig * (1 + x_fp32 * (1 - sig))
29+
dx = d_x_silu * dgrad * y
30+
dy = dgrad * x_silu
31+
return dx, dy
32+
33+
2034
class SiluAndMul(torch.autograd.Function):
2135
@staticmethod
2236
def forward(ctx, A, B):
37+
ctx.save_for_backward(A, B)
2338
logger.debug("GEMS_CAMBRICON SILU AND MUL FORWARD")
2439
return silu_and_mul_kernel(A, B)
2540

41+
def backward(ctx, grad_output):
42+
A, B = ctx.saved_tensors
43+
grad_A, grad_B = silu_and_mul_grad_kernel(A, B, grad_output)
44+
return grad_A, grad_B
45+
2646

2747
def silu_and_mul(A, B):
2848
return SiluAndMul.apply(A, B)

0 commit comments

Comments
 (0)