Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.git
.github
.specify
specs
build
dist
*.egg-info
__pycache__
.venv
venv
.env
.env.*
*.log
.DS_Store
benchmark/*.log
tests/__pycache__
*.pyc
45 changes: 45 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,56 @@
# python build files
*.pyc
*.pyo
__pycache__/
*.egg-info/
.venv/
venv/
dist/
.env
.env.*

build

# vscode
.vscode/
.idea/
.DS_Store
*.tmp
*.swp

# benchmark run logs (benchmark/run_suite.py writes one per benchmark)
benchmark/*.log

# AI assistant scratch.
# Spec Kit plans stay local. .claude/skills/ stays tracked.
# Ignore tool indexes, transcripts, and generation scratch only.
.specify/
specs/
.cursor/
.cursor-*/
*.cursor-*
.cursorrules
.cursorindexingignore
agent-transcripts/
agent-logs/
*agent-transcript*
*agent-state*
*.agent.jsonl
*.agent.log

# Claude Code local state (not project skills)
.claude/settings.local.json
.claude/*.local.json
.claude/*.local.md
.claude/local/
.claude/projects/
.claude/sessions/
.claude/cache/
.claude/debug/
.claude/todos/
.claude/shell-snapshots/
.claude/ide/
.claude/statsig/
.claude/transcripts/
.claude/history.jsonl
.claude/**/*.jsonl
55 changes: 55 additions & 0 deletions Dockerfile.xpu
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Torch 2.14.0+xpu, oneAPI 2026.1, and SGLang 0.5.22 are already in this image.
# The checkpoint stays on the node at /tank/nas/models and is not copied here.
# pip-installing this repo would replace sgl_kernel and drop FMHA and GDN.
# Those stay in the base image. This image only adds the GPTQ op.
FROM lmsysorg/sglang:v0.5.22-xpu

COPY include /opt/sgl-kernel-xpu/include
COPY src/sycl/gptq_gemm.cpp src/sycl/gptq_entry_probe.cpp src/sycl/gptq_register.cpp src/sycl/gdn_verify_entry.cpp src/sycl/causal_conv1d.cpp src/sycl/causal_conv1d_verify.hpp src/sycl/causal_conv1d_token_parallel.hpp src/sycl/Utils.h src/sycl/SYCLHelpers.h src/sycl/SGLKernelPerf.h /opt/sgl-kernel-xpu/src/
COPY src/sycl/gdn_attn/gated_delta_rule.hpp /opt/sgl-kernel-xpu/src/gdn_attn/gated_delta_rule.hpp
COPY src/jit/jit_arch.h /opt/sgl-kernel-xpu/src/jit/jit_arch.h

RUN set -eux; \
ICPX=/opt/intel/oneapi/compiler/2026.1/bin/icpx; \
TORCH="$(python -c 'import pathlib, torch; print(pathlib.Path(torch.__file__).parent)')"; \
"$ICPX" -fsycl -fsycl-targets=spir64_gen \
-Xspirv-translator -spirv-ext=+SPV_INTEL_split_barrier,+SPV_INTEL_2d_block_io,+SPV_INTEL_subgroup_matrix_multiply_accumulate \
-Xsycl-target-backend "-device bmg" \
-std=c++20 -O2 -fPIC -shared \
-I/opt/sgl-kernel-xpu/include \
-I/opt/sgl-kernel-xpu/src \
-I"$TORCH/include" \
-I"$TORCH/include/torch/csrc/api/include" \
/opt/sgl-kernel-xpu/src/gptq_register.cpp \
/opt/sgl-kernel-xpu/src/gptq_gemm.cpp \
/opt/sgl-kernel-xpu/src/gptq_entry_probe.cpp \
/opt/sgl-kernel-xpu/src/gdn_verify_entry.cpp \
/opt/sgl-kernel-xpu/src/causal_conv1d.cpp \
-o /opt/sgl-kernel-xpu/sgl_gptq_ops.so \
-L"$TORCH/lib" -Wl,-rpath,"$TORCH/lib" \
-ltorch -ltorch_xpu -ltorch_cpu -lc10

COPY python/sgl_kernel/gptq_loader.py /opt/sgl-kernel-xpu/python/gptq_loader.py
COPY scripts /opt/sgl-kernel-xpu/scripts
COPY deploy/sglang-gptq-xpu.patch deploy/sglang-qwen35-ba.patch deploy/sglang-qwen35-time.patch deploy/sglang-xpu-page.patch deploy/sglang-mamba-page.patch deploy/sglang-xpu-gdn-page.patch deploy/sglang-lmhead.patch deploy/sglang-loop-time.patch deploy/sglang-page1-graph.patch deploy/sglang-stream-token-ids.patch deploy/sglang-gdn-verify.patch /opt/sgl-kernel-xpu/deploy/

RUN set -eux; \
kernel="$(python -c 'import pathlib, sgl_kernel; print(pathlib.Path(sgl_kernel.__file__).parent)')"; \
cp /opt/sgl-kernel-xpu/python/gptq_loader.py "$kernel/gptq_loader.py"; \
printf '\nfrom sgl_kernel.gptq_loader import gptq_entry_probe, gptq_gemm\n' >> "$kernel/__init__.py"; \
site="$(python -c 'import pathlib, sglang; print(pathlib.Path(sglang.__file__).resolve().parent.parent)')"; \
patch -p2 -d "$site" < /opt/sgl-kernel-xpu/deploy/sglang-gptq-xpu.patch; \
patch -p2 -d "$site" < /opt/sgl-kernel-xpu/deploy/sglang-qwen35-ba.patch; \
patch -p2 -d "$site" < /opt/sgl-kernel-xpu/deploy/sglang-qwen35-time.patch; \
patch -p2 -d "$site" < /opt/sgl-kernel-xpu/deploy/sglang-xpu-page.patch; \
patch -p2 -d "$site" < /opt/sgl-kernel-xpu/deploy/sglang-mamba-page.patch; \
patch -p2 -d "$site" < /opt/sgl-kernel-xpu/deploy/sglang-xpu-gdn-page.patch; \
patch -p2 -d "$site" < /opt/sgl-kernel-xpu/deploy/sglang-gdn-verify.patch; \
patch -p2 -d "$site" < /opt/sgl-kernel-xpu/deploy/sglang-lmhead.patch; \
patch -p2 -d "$site" < /opt/sgl-kernel-xpu/deploy/sglang-loop-time.patch; \
patch -p2 -d "$site" < /opt/sgl-kernel-xpu/deploy/sglang-page1-graph.patch; \
patch -p2 -d "$site" < /opt/sgl-kernel-xpu/deploy/sglang-stream-token-ids.patch; \
python /opt/sgl-kernel-xpu/scripts/check_sglang_version.py

WORKDIR /opt/sgl-kernel-xpu
CMD ["python3", "/opt/sgl-kernel-xpu/scripts/run_gptq_mode.py"]
42 changes: 42 additions & 0 deletions benchmark/bench_gptq_gemm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Time gptq_gemm on XPU. A machine without XPU prints a skip and is not a B70 result."""

import sys

import torch


def main() -> None:
if not hasattr(torch, "xpu") or not torch.xpu.is_available():
print("XPU unavailable; this run is not an Intel Arc Pro B70 result")
return
from sgl_kernel import gptq_gemm

device = torch.device("xpu")
k, n = 4096, 4096
for m in (1, 16):
act = torch.randn(m, k, device=device, dtype=torch.bfloat16)
qweight = torch.randint(0, 2**31 - 1, (k // 8, n), device=device, dtype=torch.int32)
qzeros = torch.randint(0, 2**31 - 1, (k // 128, n // 8), device=device, dtype=torch.int32)
scales = torch.rand(k // 128, n, device=device, dtype=torch.bfloat16) * 0.05 + 0.01
g_idx = (torch.arange(k, device=device) // 128).to(torch.int32)
for _ in range(3):
gptq_gemm(act, qweight, qzeros, scales, g_idx, False, 4, 1)
torch.xpu.synchronize()
start = torch.xpu.Event(enable_timing=True)
end = torch.xpu.Event(enable_timing=True)
iters = 10
start.record()
for _ in range(iters):
gptq_gemm(act, qweight, qzeros, scales, g_idx, False, 4, 1)
end.record()
torch.xpu.synchronize()
ms = start.elapsed_time(end) / iters
print(f"gptq_gemm M={m} K={k} N={n} {ms:.3f} ms")


if __name__ == "__main__":
try:
main()
except Exception as exc:
print(f"benchmark did not run: {exc}", file=sys.stderr)
raise
68 changes: 68 additions & 0 deletions deploy/k8s/test-job.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
apiVersion: batch/v1
kind: Job
metadata:
name: sgl-gptq-xpu-test
spec:
backoffLimit: 0
template:
spec:
restartPolicy: Never
nodeName: hal
containers:
- name: gptq
image: ${IMAGE}:${TAG}
imagePullPolicy: Always
env:
- name: MODE
value: "${MODE}"
- name: STAGE
value: "${STAGE}"
- name: BASELINE_TPS
value: "${BASELINE_TPS}"
- name: SGL_GPTQ_PROFILE
value: "${SGL_GPTQ_PROFILE}"
- name: MAX_NEW_TOKENS
value: "${MAX_NEW_TOKENS}"
- name: SGL_GPTQ_STEP
value: "${SGL_GPTQ_STEP}"
- name: SGL_GPTQ_PAGE_SIZE
value: "${SGL_GPTQ_PAGE_SIZE}"
- name: SGL_GPTQ_CONTEXT_LENGTH
value: "${SGL_GPTQ_CONTEXT_LENGTH}"
- name: SGL_GPTQ_SPEC
value: "${SGL_GPTQ_SPEC}"
- name: SGL_GPTQ_SPEC_STEPS
value: "${SGL_GPTQ_SPEC_STEPS}"
- name: SGL_GPTQ_SPEC_DRAFT_TOKENS
value: "${SGL_GPTQ_SPEC_DRAFT_TOKENS}"
- name: SGL_GPTQ_MAMBA_CACHE
value: "${SGL_GPTQ_MAMBA_CACHE}"
- name: SGL_GPTQ_PP
value: "${SGL_GPTQ_PP}"
- name: SGL_GPTQ_TG
value: "${SGL_GPTQ_TG}"
- name: SGL_GPTQ_BATCH
value: "${SGL_GPTQ_BATCH}"
- name: SGL_GPTQ_GRAPH_BS
value: "${SGL_GPTQ_GRAPH_BS}"
- name: SGL_GPTQ_BATCH_WIDTHS
value: "${SGL_GPTQ_BATCH_WIDTHS}"
- name: SGL_GPTQ_MAX_RUNNING
value: "${SGL_GPTQ_MAX_RUNNING}"
- name: SGL_GPTQ_MEM_FRACTION
value: "${SGL_GPTQ_MEM_FRACTION}"
- name: MODEL_DIR
value: "/tank/nas/models/Qwen3.8-27B-TURBO-DF735-882-NM-DAU-GPTQ-Int4-g128-tuned"
resources:
requests:
gpu.intel.com/xe: 1
limits:
gpu.intel.com/xe: 1
volumeMounts:
- name: models
mountPath: /tank/nas/models
volumes:
- name: models
hostPath:
path: /tank/nas/models
type: Directory
Loading