{"record":{"id":"e4a29735518c82d3","repo":"sgl-project/sglang","slug":"lplb-fused-solver-requires-float32-got-a-dtype-a","errorCode":null,"errorMessage":"LPLB fused solver requires float32; got A.dtype={A.dtype}.","messagePattern":"LPLB fused solver requires float32; got A\\.dtype=(.+?)\\.","errorType":"validation","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/sglang/kernels/ops/lplb/torch_solver.py","lineNumber":133,"sourceCode":"        num_iters: Number of barrier iterations (default 5).\n\n    Returns:\n        x: Solution vector, shape (NV,), float32. The kernel writes 0.5\n        for every entry on non-convergence.\n    \"\"\"\n    nc, nv = A.shape\n    assert b.shape == (nc,), f\"b shape mismatch: {b.shape} vs ({nc},)\"\n    assert c.shape == (nv,), f\"c shape mismatch: {c.shape} vs ({nv},)\"\n\n    _init_fused_backend()\n    if not _FUSED_AVAILABLE:\n        raise RuntimeError(f\"LPLB fused solver unavailable: {_unavailable_reason()}\")\n    if not A.is_cuda:\n        raise RuntimeError(\n            f\"LPLB fused solver requires CUDA tensors; got A on {A.device}.\"\n        )\n    if A.dtype != torch.float32:\n        raise RuntimeError(\n            f\"LPLB fused solver requires float32; got A.dtype={A.dtype}.\"\n        )\n    return _FUSED_SOLVE_IPM(A, b, c, num_iters=num_iters)\n\n\ndef solve_ipm_torch_reference(\n    A: torch.Tensor,\n    b: torch.Tensor,\n    c: torch.Tensor,\n    num_iters: int = 5,\n) -> torch.Tensor:\n    \"\"\"Pure-torch reference for the fused IPM kernel — testing only.\n\n    Mirrors the barrier-method iteration in ``csrc/lplb/ipm.cuh``\n    step-for-step so the two can be compared numerically:\n\n      x <- 1\n      for _ in range(num_iters):","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/kernels/ops/lplb/torch_solver.py#L115-L151","documentation":"The fused IPM kernel is compiled for float32 only; A (and by extension the problem) must be float32. Other dtypes raise before launch because no fp16/bf16 variant exists for this solver.","triggerScenarios":"Calling solve_ipm with A in float64 (e.g. after numpy conversion default), float16, or bfloat16.","commonSituations":"Data round-tripped through numpy (np.float64) then back to torch; mixed-precision model weights fed directly; explicit .half() pipelines.","solutions":["Cast inputs: A = A.float(); b = b.float(); c = c.float() before solve_ipm","Ensure upstream conversion code uses torch.float32 when building A, b, c","If you need fp16 results, solve in fp32 then cast the outputs"],"exampleFix":"// before\nx, y, s = solve_ipm(A.double(), b, c)\n\n// after\nx, y, s = solve_ipm(A.float(), b.float(), c.float())","handlingStrategy":"type-guard","validationCode":"A, b, c = (t.to(torch.float32) for t in (A, b, c))","typeGuard":"def is_fp32(*ts: torch.Tensor) -> bool:\n    return all(t.dtype is torch.float32 for t in ts)","tryCatchPattern":null,"preventionTips":["torch.from_numpy(...) defaults to float64 — always annotate .float()","Build A/b/c with dtype=torch.float32 at construction rather than casting at call sites"],"tags":["dtype-validation","float32","lplb"],"backgroundTag":"unsupported-tensor-dtype","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}