[Bug] [Relax][CUDA] Wrong result for a K=1 matmul chain after AdjustMatmulOrder
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 48/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- python
- Lĩnh vực
- compilers, machine-learning
Hướng nghiên cứu
Start by reading the AdjustMatmulOrder transform and the DLight reverse_compute_inline path mentioned in the report, then run the supplied reproducer on a CUDA-enabled TVM build. Compare the scheduled TIR for the original and transformed modules, especially where the clipped exp chain appears in reduction initialization and update. Done means both compiled variants match the NumPy result for the K=1 matmul chain.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Expected behavior
The original module and the module after AdjustMatmulOrder should return the same values. Both should match the NumPy calculation in the script below.
Actual behavior
I ran into this with a chain of two matmuls followed by two clipped exp operations. The first matmul has a reduction dimension of 1. Both versions compile and run, but the transformed version returns different values:
OFF first = 0.6067528 max abs error = 0.0
OFF allclose = True
ON first = 0.7993563 max abs error = 0.19286269
ON allclose = False
The OFF result matches NumPy. The ON result does not: all 30 output values fail rtol=0.02, atol=0.002. I can also reproduce this with a different random input.
In the scheduled ON TIR, the exp chain is in both the reduction initialization and update after DLight's reverse_compute_inline. It should run once on the completed matmul result.
Environment
- Apache TVM
0.26.dev0+source.8f328e8(source build) - Linux
6.8.0-52-generic, x86-64; Python3.11.16 - NVIDIA RTX A6000, driver
550.120, CUDA toolkit12.4, targetsm_86 - Relax default CUDA compilation pipeline
Steps to reproduce
Save as repro_k1_matmul_exp.py and run python repro_k1_matmul_exp.py on a CUDA-enabled TVM build:
import numpy as np
import tvm
from tvm import relax as R
from tvm.script import ir as I, relax as S, tirx as T
@I.ir_module
class Before:
@S.function
def main(
a: S.Tensor((1, 10), "float16"),
b: S.Tensor((20, 1), "float16"),
c: S.Tensor((20, 3), "float16"),
) -> S.Tensor((10, 3), "float32"):
with S.dataflow():
outer = S.matmul(b, a, out_dtype=None)
transposed = S.permute_dims(outer, axes=None)
matmul = S.matmul(transposed, c, out_dtype="float32")
first = S.exp(
S.subtract(
S.clip(matmul, T.float64(-0.25), T.float64(0.25)),
S.multiply(
S.clip(matmul, T.float64(-0.25), T.float64(2.0)),
S.const(0.5, "float32"),
),
)
)
second = S.exp(
S.subtract(
S.clip(matmul, T.float64(-0.25), T.float64(0.25)),
S.multiply(
S.clip(first, T.float64(-0.25), T.float64(2.0)),
S.const(0.5, "float32"),
),
)
)
S.output(second)
return second
dev = tvm.cuda(0)
target = tvm.target.Target({
"kind": "cuda",
"arch": "sm_" + dev.compute_version.replace(".", ""),
"host": {"kind": "llvm", "mcpu": "generic"},
})
with tvm.transform.PassContext(opt_level=2):
After = R.transform.AdjustMatmulOrder()(Before)
rng = np.random.default_rng(710000)
a, b, c = [
((rng.integers(0, 2, size=shape, dtype="int32") * 2 - 1) / 16).astype("float16")
for shape in ((1, 10), (20, 1), (20, 3))
]
outer = (b @ a).astype("float16")
matmul = outer.T.astype("float32") @ c.astype("float32")
expected = matmul.copy()
for _ in range(2):
expected = np.exp(
np.clip(matmul, -0.25, 0.25)
- 0.5 * np.clip(expected, -0.25, 2.0)
)
# Freeze both branches before compiling either one.
frozen = {"OFF": tvm.ir.save_json(Before), "ON": tvm.ir.save_json(After)}
for name, serialized in frozen.items():
with target, tvm.transform.PassContext(
opt_level=2, disabled_pass=["AdjustMatmulOrder"]
):
ex = tvm.compile(
tvm.ir.load_json(serialized),
target=target,
relax_pipeline="default",
tir_pipeline="default",
)
vm = R.VirtualMachine(ex, dev)
output = vm["main"](*[
tvm.runtime.tensor(x.copy(), dev) for x in (a, b, c)
]).numpy()
print(name, "first =", output.flat[0],
"max abs error =", np.max(np.abs(output - expected)))
print(name, "allclose =", np.allclose(
output, expected, rtol=0.02, atol=0.002
))
Triage
- needs-triage
- type: bug
- backend:cuda
- Ngôn ngữ chính
- Python
- Star
- 13.9k
- Fork
- 4k
- Merge trung bình
- 8 giờ 2 phút
- Pull request đã merge (30 ngày)
- 180
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của apache/tvm
-
needs-triage type: bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 80/100
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug] [Relax][ONNX] OneHot does not convert floating-point depth to int64Có thể đã có người làm @tandede đã nhận 1 ngày trước. Đang mởneeds-triage type: bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Maintainer thường phản hồi trong vòng 1 ngày
-
needs-triage type: bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Maintainer thường phản hồi trong vòng 1 ngày
-
needs-triage type: bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug][Relax] ReorderTakeAfterMatmul fails on vector dot productsCó thể đã có người làm @hiyufan đã nhận 10 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
apache/tvm#20595 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
huggingface/deep-rl-class#723 ·
-
[tool] bug: Qwen3 XML tool parser raises on `...` argument values (Ellipsis is not JSON serializable)Có thể đã có người làm @super-yuki đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 87/100
verl-project/verl#8559 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
TencentCloud/octop-harness#228 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
google/osv-scalibr#2585 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
NousResearch/hermes-agent#149323 ·
Maintainer thường phản hồi trong vòng 1 ngày