[CI] Collapse the EAGLE launch matrix and the scoring engine boots on the per-commit runners (#33756)

This commit is contained in:
Liangsheng Yin
2026-08-05 16:43:19 -07:00
committed by GitHub
parent 5424d2039c
commit 3869fe556f
22 changed files with 403 additions and 444 deletions
+2 -2
View File
@@ -161,7 +161,7 @@ class TestDFlashServerNoCudaGraph(TestDFlashServerBase):
other_launch_args = ["--disable-cuda-graph"]
class TestDFlashServerSpecV2(TestDFlashServerBase):
class TestDFlashServerOverlap(TestDFlashServerBase):
disable_overlap = False
def test_radix_attention(self):
@@ -169,7 +169,7 @@ class TestDFlashServerSpecV2(TestDFlashServerBase):
assert self.process.poll() is None
class TestDFlashServerSpecV2PlanStream(TestDFlashServerSpecV2):
class TestDFlashServerOverlapPlanStream(TestDFlashServerOverlap):
overlap_plan_stream = True
@@ -1,5 +1,7 @@
"""EAGLE3 spec-decoding core: overlap (spec v2) x no-overlap (spec v1) matrix,
same standard config (topk=1, page_size=1), only ``disable_overlap`` differs.
"""EAGLE3 spec-decoding core: overlap x no-overlap matrix at the standard
config (topk=1, page_size=1); only ``disable_overlap`` differs. Both run the
same EAGLEWorkerV2 -- the scheduler just drives it synchronously when overlap
is off.
flashinfer is pinned (the 5090 default) so a default-selection change can't
silently alter what this exercises.
"""
@@ -35,13 +37,13 @@ class _Core(Eagle3Base):
class TestEagle3Overlap(_Core, *_KITS):
"""Spec v2 (overlap scheduler on)."""
"""Overlap scheduler on."""
disable_overlap = False
class TestEagle3NoOverlap(_Core, *_KITS):
"""Spec v1 (overlap scheduler off)."""
"""Overlap scheduler off (synchronous)."""
disable_overlap = True
@@ -10,7 +10,6 @@ from sglang.srt.environ import envs
from sglang.test.ci.ci_register import register_cuda_ci
from sglang.test.kits.spec_server_kits import (
SpecAccuracyKit,
SpecCorrectnessKit,
SpecFeatureKit,
SpecLogprobKit,
SpecPenaltyKit,
@@ -18,11 +17,16 @@ from sglang.test.kits.spec_server_kits import (
)
from sglang.test.server_fixtures.spec_eagle_fixture import Eagle3Base, EagleLlama2Base
register_cuda_ci(est_time=600, stage="base-b", runner_config="1-gpu-large")
register_cuda_ci(est_time=250, stage="base-b", runner_config="1-gpu-large")
class TestEagle3Fa3(Eagle3Base, SpecCorrectnessKit, SpecAccuracyKit, SpecLogprobKit):
"""EAGLE3 spec v2 topk=1 on fa3 (the H200 default backend)."""
class TestEagle3Fa3(Eagle3Base, SpecAccuracyKit, SpecLogprobKit):
"""EAGLE3 topk=1 on fa3 (the H200 default backend), overlap on.
No SpecCorrectnessKit: those checks are scheduler/sampling behaviour, which
the 5090 runs already cover. Logprob losslessness stays -- it reads through
the verify output, which the attention unit cases do not reach.
"""
attention_backend = "fa3"
disable_overlap = False
@@ -37,7 +41,7 @@ class TestEagleLlama2Fa3Page256(
SpecPerfKit,
SpecFeatureKit,
):
"""EAGLE/Llama-2 topk=5 tree on fa3 + page_size=256 (spec v1)."""
"""EAGLE/Llama-2 topk=5 tree on fa3 + page_size=256, overlap off."""
spec_topk = 5
spec_steps = 8
@@ -1,7 +1,7 @@
"""page_size > 1 variants at topk=1 (flashinfer).
"""EAGLE3 chain drafting (topk=1) at page_size > 1, flashinfer.
EAGLE3 page64 (spec v2) + EAGLE/Llama-2 page4 (spec v1). topk>1 page variants
live in test_spec_eagle_topk.py. Runs on the cheap (5090) runner.
topk=1 takes its own fast path in the draft worker, so this cell is not
covered by the tree variants in test_spec_eagle_topk_page.py.
"""
import unittest
@@ -10,30 +10,28 @@ from sglang.srt.environ import envs
from sglang.test.ci.ci_register import register_cuda_ci
from sglang.test.kits.spec_server_kits import (
SpecAccuracyKit,
SpecCorrectnessKit,
SpecFeatureKit,
SpecLogprobKit,
)
from sglang.test.server_fixtures.spec_eagle_fixture import Eagle3Base, EagleLlama2Base
from sglang.test.server_fixtures.spec_eagle_fixture import Eagle3Base
register_cuda_ci(est_time=360, stage="base-b", runner_config="1-gpu-small")
register_cuda_ci(est_time=230, stage="base-b", runner_config="1-gpu-small")
class TestEagle3Page64(Eagle3Base, SpecAccuracyKit, SpecLogprobKit, SpecFeatureKit):
"""EAGLE3 spec v2, page_size=64 (flashinfer): + logprob losslessness."""
class TestEagle3Page64(
Eagle3Base,
SpecCorrectnessKit,
SpecAccuracyKit,
SpecLogprobKit,
SpecFeatureKit,
):
"""Overlap scheduler, page_size=64: + logprob losslessness."""
page_size = 64
disable_overlap = False
env_overrides = ((envs.SGLANG_ENABLE_STRICT_MEM_CHECK_DURING_BUSY, 1),)
class TestEagleLlama2Page4Topk1(EagleLlama2Base, SpecAccuracyKit, SpecFeatureKit):
"""Llama-2 topk=1 + page_size=4."""
spec_topk = 1
spec_tokens = 6
page_size = 4
env_overrides = ((envs.SGLANG_ENABLE_STRICT_MEM_CHECK_DURING_BUSY, 1),)
if __name__ == "__main__":
unittest.main()
@@ -27,7 +27,7 @@ class _Eagle3ParityBase(Eagle3Base):
@unittest.skipIf(_is_xpu, "CUDA runner only")
class TestEagle3ParityCUDA(SpecParityKit, _Eagle3ParityBase):
"""EAGLE3 spec v2 (flashinfer, overlap) greedy output == non-spec reference.
"""EAGLE3 (flashinfer, overlap) greedy output == non-spec reference.
SpecParityKit is first so its setUpClass runs the reference server (and tears
it down) before the fixture launches the spec server -- sequential, one model
@@ -1,18 +1,15 @@
"""Perf + stress: throughput, retract-under-pressure, abort storms, timeouts.
"""Perf + stress: throughput and retract-under-pressure.
These need memory headroom / measure load behavior, so they run on the large
(Hopper) runner.
These need memory headroom / measure load behaviour, so they run on the large
(Hopper) runner. The scheduler timeout paths carry no spec-specific state, so
they live in unit/managers/test_scheduler_timeouts.py plus the cheap e2e in
scheduler/test_scheduler_control.py.
"""
import unittest
from sglang.srt.environ import envs
from sglang.test.ci.ci_register import register_cuda_ci
from sglang.test.kits.abort_timeout_kit import (
AbortAllMixin,
RunningTimeoutTwoWaveMixin,
WaitingTimeoutMixin,
)
from sglang.test.kits.spec_server_kits import (
SpecAccuracyKit,
SpecFeatureKit,
@@ -20,11 +17,11 @@ from sglang.test.kits.spec_server_kits import (
)
from sglang.test.server_fixtures.spec_eagle_fixture import Eagle3Base, EagleLlama2Base
register_cuda_ci(est_time=780, stage="base-b", runner_config="1-gpu-large")
register_cuda_ci(est_time=440, stage="base-b", runner_config="1-gpu-large")
class TestEagle3Perf(Eagle3Base, SpecPerfKit):
"""Decode throughput (max_new_tokens=1) on EAGLE3 spec v2."""
"""Decode throughput (max_new_tokens=1) on EAGLE3."""
disable_overlap = False
env_overrides = ((envs.SGLANG_ENABLE_STRICT_MEM_CHECK_DURING_BUSY, 1),)
@@ -42,7 +39,7 @@ class TestEagleLlama2Retract(EagleLlama2Base, SpecAccuracyKit, SpecFeatureKit):
class TestEagle3Topk16V2Retract(Eagle3Base, SpecAccuracyKit, SpecFeatureKit):
"""EAGLE3 topk=16 tree on spec v2 under retract; must not leak KV. Stresses
"""EAGLE3 topk=16 tree under retract; must not leak KV. Stresses
the accepted-path KV move (move_accept_tokens_to_target_kvcache)."""
spec_topk = 16
@@ -58,27 +55,5 @@ class TestEagle3Topk16V2Retract(Eagle3Base, SpecAccuracyKit, SpecFeatureKit):
)
class TestEagleLlama2AbortAll(EagleLlama2Base, AbortAllMixin):
abort_all_max_new_tokens = 4000
env_overrides = ((envs.SGLANG_ENABLE_STRICT_MEM_CHECK_DURING_BUSY, 1),)
class TestEagleLlama2WaitingTimeout(EagleLlama2Base, WaitingTimeoutMixin):
max_running_requests = 1
env_overrides = (
(envs.SGLANG_REQ_WAITING_TIMEOUT, 0.001),
(envs.SGLANG_ENABLE_STRICT_MEM_CHECK_DURING_BUSY, 1),
)
class TestEagleLlama2RunningTimeout(EagleLlama2Base, RunningTimeoutTwoWaveMixin):
# Regression: https://github.com/sgl-project/sglang/pull/18760
max_running_requests = 16
env_overrides = (
(envs.SGLANG_REQ_RUNNING_TIMEOUT, 3),
(envs.SGLANG_ENABLE_STRICT_MEM_CHECK_DURING_BUSY, 1),
)
if __name__ == "__main__":
unittest.main()
@@ -1,8 +1,7 @@
"""topk > 1 tree drafting (EAGLE3 topk16 + EAGLE/Llama-2 topk8).
"""topk > 1 tree drafting at page_size=1 (EAGLE3 topk16 + EAGLE/Llama-2 topk8).
topk > 1 routes to spec v1, except page_size==1 which can also stay on spec v2
(overlap). flashinfer is pinned because this runs on the cheap (5090) runner,
where fa3 (Hopper-only) isn't available -- functional sanity only, no perf/stress.
flashinfer is pinned because this runs on the cheap (5090) runner, where fa3
(Hopper-only) isn't available -- functional sanity only, no perf/stress.
(topk > 1 on fa3 is covered on the Hopper runner in test_spec_eagle_fa3.py.)
"""
@@ -10,24 +9,37 @@ import unittest
from sglang.srt.environ import envs
from sglang.test.ci.ci_register import register_cuda_ci
from sglang.test.kits.abort_timeout_kit import AbortAllMixin
from sglang.test.kits.spec_server_kits import (
SpecAccuracyKit,
SpecCorrectnessKit,
SpecFeatureKit,
SpecHiddenStatesKit,
SpecLogprobKit,
SpecPenaltyKit,
)
from sglang.test.server_fixtures.spec_eagle_fixture import Eagle3Base, EagleLlama2Base
register_cuda_ci(est_time=1180, stage="base-b", runner_config="1-gpu-small")
register_cuda_ci(est_time=870, stage="base-b", runner_config="1-gpu-small")
class TestEagle3Topk16(Eagle3Base, SpecCorrectnessKit, SpecAccuracyKit, SpecLogprobKit):
"""EAGLE3 topk=16 tree (spec v1): correctness + gsm8k + logprob losslessness."""
class TestEagle3Topk16(
Eagle3Base,
SpecCorrectnessKit,
SpecAccuracyKit,
SpecLogprobKit,
SpecFeatureKit,
SpecHiddenStatesKit,
):
"""EAGLE3 topk=16 tree, overlap scheduler: guards the accepted-path
compaction (via logprob_decode_match_prefill) and the per-request
hidden-state stride slicing that the same compaction feeds.
"""
spec_topk = 16
spec_tokens = 64
disable_overlap = True # synchronous baseline; SpecV2 subclass flips overlap on
disable_overlap = False
enable_return_hidden_states = True
cuda_graph_max_bs_decode = 5
acc_length_thres = 3.1
batch_accept_len_thres = 1.75
@@ -35,13 +47,6 @@ class TestEagle3Topk16(Eagle3Base, SpecCorrectnessKit, SpecAccuracyKit, SpecLogp
env_overrides = ((envs.SGLANG_ENABLE_STRICT_MEM_CHECK_DURING_BUSY, 1),)
class TestEagle3Topk16SpecV2(TestEagle3Topk16, SpecFeatureKit):
"""EAGLE3 topk=16 tree on spec v2 (overlap, page1): guards the v2 tree path's
accepted-path compaction, validated by logprob_spec_v2_match."""
disable_overlap = False
class TestEagleLlama2Suite(
EagleLlama2Base,
SpecCorrectnessKit,
@@ -49,9 +54,16 @@ class TestEagleLlama2Suite(
SpecLogprobKit,
SpecPenaltyKit,
SpecFeatureKit,
AbortAllMixin,
):
"""EAGLE/Llama-2 topk=8 full coverage (kits listed in bases)."""
"""EAGLE/Llama-2 topk=8 full coverage (kits listed in bases).
Hosts AbortAllMixin: aborting mid-decode has to release the tree draft
state, and the strict mem check below turns a leak into a failure. It needs
no server flags of its own, so it rides this launch.
"""
abort_all_max_new_tokens = 4000
env_overrides = ((envs.SGLANG_ENABLE_STRICT_MEM_CHECK_DURING_BUSY, 1),)
@@ -1,9 +1,10 @@
"""topk > 1 tree drafting at page_size > 1 (EAGLE3 topk8 + EAGLE/Llama-2 topk8).
"""EAGLE3 tree drafting (topk > 1) at page_size > 1, flashinfer (fa3 is
Hopper-only).
page64 stays on spec v2 (overlap), page4 runs on spec v1 (no overlap). flashinfer is
pinned because this runs on the cheap (5090) runner, where fa3 (Hopper-only) isn't
available -- functional sanity only, no perf/stress. (page>1 topk>1 on fa3 is covered
on the Hopper runner in test_spec_eagle_fa3.py.)
page_size=4 with 32 draft tokens spreads the draft window over several pages --
the layout the unit fixture refuses to build (tree draft is pinned to
page_size=1 there, see speculative_draft_runner.py). The window-inside-one-page
regime is covered by test_spec_eagle_fa3.py page256 on the Hopper runner.
"""
import unittest
@@ -13,29 +14,26 @@ from sglang.test.ci.ci_register import register_cuda_ci
from sglang.test.kits.spec_server_kits import (
SpecAccuracyKit,
SpecFeatureKit,
SpecLogprobKit,
)
from sglang.test.server_fixtures.spec_eagle_fixture import Eagle3Base, EagleLlama2Base
from sglang.test.server_fixtures.spec_eagle_fixture import Eagle3Base
register_cuda_ci(est_time=720, stage="base-b", runner_config="1-gpu-small")
register_cuda_ci(est_time=345, stage="base-b", runner_config="1-gpu-small")
class TestEagle3Page64Topk8(Eagle3Base, SpecAccuracyKit, SpecFeatureKit):
"""EAGLE3 topk=8 tree + page_size=64 (spec v2)."""
class TestEagle3Page4Topk8(Eagle3Base, SpecAccuracyKit, SpecLogprobKit, SpecFeatureKit):
"""Overlap scheduler, topk=8 tree, page_size=4."""
page_size = 64
page_size = 4
spec_topk = 8
spec_tokens = 32
disable_overlap = False
# Preset accept-length values are topk=1 numbers -- loose for a topk=8
# tree; tighten once CI reports the actuals.
gsm8k_accept_len_thres = 2.0
cuda_graph_max_bs_decode = 5
env_overrides = ((envs.SGLANG_ENABLE_STRICT_MEM_CHECK_DURING_BUSY, 1),)
class TestEagleLlama2Page4Topk8(EagleLlama2Base, SpecAccuracyKit, SpecFeatureKit):
"""Llama-2 topk>1 tree + page_size=4 (spec v1)."""
page_size = 4
env_overrides = ((envs.SGLANG_ENABLE_STRICT_MEM_CHECK_DURING_BUSY, 1),)
if __name__ == "__main__":
unittest.main()
@@ -1,6 +1,8 @@
"""triton attention backend (EAGLE3 topk=1 chain + EAGLE/Llama-2 topk=8 tree).
"""triton attention backend, EAGLE3 chain drafting.
triton runs everywhere, so this stays on the cheap (5090) runner.
triton runs everywhere, so this stays on the cheap (5090) runner. triton tree
verify is covered by attention/unittests/dense/test_triton.py, and the tree
accept-path compaction e2e lives in test_spec_eagle_topk.py.
"""
import unittest
@@ -11,13 +13,12 @@ from sglang.test.kits.matched_stop_kit import MatchedStopMixin
from sglang.test.kits.spec_server_kits import (
SpecAccuracyKit,
SpecFeatureKit,
SpecHiddenStatesKit,
SpecLogprobKit,
SpecPenaltyKit,
)
from sglang.test.server_fixtures.spec_eagle_fixture import Eagle3Base, EagleLlama2Base
from sglang.test.server_fixtures.spec_eagle_fixture import Eagle3Base
register_cuda_ci(est_time=350, stage="base-b", runner_config="1-gpu-small")
register_cuda_ci(est_time=230, stage="base-b", runner_config="1-gpu-small")
class TestEagle3Triton(
@@ -28,7 +29,7 @@ class TestEagle3Triton(
SpecPenaltyKit,
SpecFeatureKit,
):
"""EAGLE3 spec v2 on triton (kits listed in bases)."""
"""Overlap scheduler on triton (kits listed in bases)."""
attention_backend = "triton"
max_running_requests = 64
@@ -38,19 +39,5 @@ class TestEagle3Triton(
env_overrides = ((envs.SGLANG_ENABLE_STRICT_MEM_CHECK_DURING_BUSY, 1),)
class TestEagleLlama2Triton(
EagleLlama2Base, SpecAccuracyKit, SpecFeatureKit, SpecHiddenStatesKit
):
"""EAGLE/Llama-2 topk=8 tree on triton.
Hosts SpecHiddenStatesKit: topk>1 exercises the tree accept-path
compaction that the per-req hidden-state stride slicing depends on.
"""
attention_backend = "triton"
enable_return_hidden_states = True
env_overrides = ((envs.SGLANG_ENABLE_STRICT_MEM_CHECK_DURING_BUSY, 1),)
if __name__ == "__main__":
unittest.main()
+13 -8
View File
@@ -4,24 +4,29 @@ from sglang.test.ci.ci_register import register_cuda_ci
from sglang.test.kits.json_constrained_kit import JSONConstrainedMixin
from sglang.test.kits.regex_constrained_kit import RegexConstrainedMixin
from sglang.test.server_fixtures.standalone_fixture import StandaloneServerBase
from sglang.test.test_utils import CustomTestCase
from sglang.test.test_utils import CustomTestCase, is_in_ci
# V2 standalone speculative decoding tests (FA3, Triton, FlashInfer backends).
# V2 standalone speculative decoding. CI runs only fa3 (the backend this is
# deployed on); triton / flashinfer stay runnable locally, and their spec verify
# numerics live in attention/unittests/dense/test_{triton,flashinfer}.py.
# Non-V2 backends moved to test_spec_standalone_extra.py.
register_cuda_ci(est_time=450, stage="base-b", runner_config="1-gpu-large")
register_cuda_ci(est_time=170, stage="base-b", runner_config="1-gpu-large")
class TestStandaloneV2SpeculativeDecodingBase(StandaloneServerBase, CustomTestCase):
class TestStandaloneV2SpeculativeDecodingBase(
StandaloneServerBase, CustomTestCase, RegexConstrainedMixin, JSONConstrainedMixin
):
# Hosts the constrained mixins: overlap is on, so they exercise the
# grammar barrier path.
attention_backend = "fa3"
class TestStandaloneV2SpeculativeDecodingTriton(
StandaloneServerBase, CustomTestCase, RegexConstrainedMixin, JSONConstrainedMixin
):
# Constrained mixins reuse this server; overlap on -> grammar barrier path.
@unittest.skipIf(is_in_ci(), "CI covers fa3 only; run locally for triton.")
class TestStandaloneV2SpeculativeDecodingTriton(StandaloneServerBase, CustomTestCase):
attention_backend = "triton"
@unittest.skipIf(is_in_ci(), "CI covers fa3 only; run locally for flashinfer.")
class TestStandaloneV2SpeculativeDecodingFlashinfer(
StandaloneServerBase, CustomTestCase
):