From 307a2b73edd84e66128c92576fb5817535e370d2 Mon Sep 17 00:00:00 2001 From: mqhc2020 Date: Wed, 25 Feb 2026 18:17:52 +0800 Subject: [PATCH] [AMD] add testcases for Qwen3 235b Instruct 2507 models (#18805) Co-authored-by: bingxche --- .../workflows/nightly-test-amd-rocm720.yml | 67 +++++++++++++ .github/workflows/nightly-test-amd.yml | 66 +++++++++++++ test/registered/amd/test_qwen3_instruct.py | 92 ++++++++++++++++++ .../registered/amd/test_qwen3_instruct_fp8.py | 92 ++++++++++++++++++ .../amd/test_qwen3_instruct_mxfp4.py | 96 +++++++++++++++++++ 5 files changed, 413 insertions(+) create mode 100644 test/registered/amd/test_qwen3_instruct.py create mode 100644 test/registered/amd/test_qwen3_instruct_fp8.py create mode 100644 test/registered/amd/test_qwen3_instruct_mxfp4.py diff --git a/.github/workflows/nightly-test-amd-rocm720.yml b/.github/workflows/nightly-test-amd-rocm720.yml index 50abc8910..c85309f67 100644 --- a/.github/workflows/nightly-test-amd-rocm720.yml +++ b/.github/workflows/nightly-test-amd-rocm720.yml @@ -32,9 +32,11 @@ on: - 'nightly-8-gpu-deepseek-v32-rocm720' - 'nightly-8-gpu-deepseek-v32-mtp-rocm720' - 'nightly-8-gpu-kimi-k25-rocm720' + - 'nightly-8-gpu-qwen3-235b-rocm720' - 'nightly-8-gpu-glm5-rocm720' # MI35x ROCm 7.2 jobs - 'nightly-test-1-gpu-mi35x-rocm720' + - 'nightly-8-gpu-mi35x-qwen3-235b-mxfp4-rocm720' - 'nightly-accuracy-8-gpu-mi35x-rocm720' - 'nightly-8-gpu-mi35x-grok1-int4-rocm720' - 'nightly-8-gpu-mi35x-grok2-rocm720' @@ -496,6 +498,36 @@ jobs: echo "$(> $GITHUB_STEP_SUMMARY || true exit ${TEST_EXIT_CODE:-0} + # 8-GPU Qwen3-235B (Accuracy + Performance) ROCm 7.2 + nightly-8-gpu-qwen3-235b-rocm720: + if: (github.repository == 'sgl-project/sglang' || github.event_name == 'pull_request') && (inputs.job_filter == '' || inputs.job_filter == 'all' || inputs.job_filter == 'nightly-8-gpu-qwen3-235b-rocm720') + runs-on: linux-mi325-gpu-8 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref || github.ref }} + + - name: Setup docker (ROCm 7.2) + run: | + touch github_summary.md + bash scripts/ci/amd/amd_ci_start_container.sh --rocm-version rocm720 + env: + GITHUB_WORKSPACE: ${{ github.workspace }} + + - name: Install dependencies + run: bash scripts/ci/amd/amd_ci_install_dependency.sh --skip-aiter-build --skip-test-time-deps + + - name: Accuracy Test + Performance Test ROCm 7.2 (8-GPU Qwen3) + timeout-minutes: 120 + run: | + > github_summary.md # Clear summary file + bash scripts/ci/amd/amd_ci_exec.sh -w /sglang-checkout/test \ + -e GITHUB_STEP_SUMMARY="/sglang-checkout/github_summary.md" \ + python3 run_suite.py --hw amd --suite nightly-8-gpu-qwen3-235b --nightly --timeout-per-file 3600 || TEST_EXIT_CODE=$? + echo "$(> $GITHUB_STEP_SUMMARY || true + exit ${TEST_EXIT_CODE:-0} + # 8-GPU GLM-5 (Accuracy) ROCm 7.2 nightly-8-gpu-glm5-rocm720: if: (github.repository == 'sgl-project/sglang' || github.event_name == 'pull_request') && (inputs.job_filter == '' || inputs.job_filter == 'all' || inputs.job_filter == 'nightly-8-gpu-glm5-rocm720') @@ -860,6 +892,39 @@ jobs: echo "$(> $GITHUB_STEP_SUMMARY || true exit ${TEST_EXIT_CODE:-0} + # MI35x 8-GPU Qwen3-235B-MXFP4 (Accuracy + Performance) ROCm 7.2 + nightly-8-gpu-mi35x-qwen3-235b-mxfp4-rocm720: + if: (github.repository == 'sgl-project/sglang' || github.event_name == 'pull_request') && (inputs.job_filter == '' || inputs.job_filter == 'all' || inputs.job_filter == 'nightly-8-gpu-mi35x-qwen3-235b-mxfp4-rocm720') + runs-on: linux-mi35x-gpu-8 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref || github.ref }} + + - name: Setup docker (ROCm 7.2) + run: | + touch github_summary.md + bash scripts/ci/amd/amd_ci_start_container.sh --rocm-version rocm720 + env: + GITHUB_WORKSPACE: ${{ github.workspace }} + + - name: Install dependencies + run: | + bash scripts/ci/amd/amd_ci_install_dependency.sh --skip-aiter-build --skip-test-time-deps + # Install tabulate for run_suite.py (missing in MI35x container) + bash scripts/ci/amd/amd_ci_exec.sh pip install tabulate + + - name: Accuracy Test + Performance Test MI35x ROCm 7.2 (8-GPU Qwen3-235B-MXFP4) + timeout-minutes: 120 + run: | + > github_summary.md # Clear summary file + bash scripts/ci/amd/amd_ci_exec.sh -w /sglang-checkout/test \ + -e GITHUB_STEP_SUMMARY="/sglang-checkout/github_summary.md" \ + python3 run_suite.py --hw amd --suite nightly-8-gpu-mi35x-qwen3-235b-mxfp4 --nightly --timeout-per-file 3600 || TEST_EXIT_CODE=$? + echo "$(> $GITHUB_STEP_SUMMARY || true + exit ${TEST_EXIT_CODE:-0} + nightly-8-gpu-mi35x-glm5-rocm720: if: (github.repository == 'sgl-project/sglang' || github.event_name == 'pull_request') && (inputs.job_filter == '' || inputs.job_filter == 'all' || inputs.job_filter == 'nightly-8-gpu-mi35x-glm5-rocm720') runs-on: linux-mi35x-gpu-8 @@ -946,6 +1011,7 @@ jobs: - nightly-8-gpu-deepseek-v32-rocm720 - nightly-8-gpu-deepseek-v32-mtp-rocm720 - nightly-8-gpu-kimi-k25-rocm720 + - nightly-8-gpu-qwen3-235b-rocm720 - nightly-8-gpu-glm5-rocm720 # MI35x ROCm 7.2 jobs - nightly-test-1-gpu-mi35x-rocm720 @@ -958,6 +1024,7 @@ jobs: - nightly-perf-8-gpu-mi35x-deepseek-v32-basic-rocm720 - nightly-perf-8-gpu-mi35x-deepseek-v32-mtp-rocm720 - nightly-8-gpu-mi35x-kimi-k25-rocm720 + - nightly-8-gpu-mi35x-qwen3-235b-mxfp4-rocm720 - nightly-8-gpu-mi35x-glm5-rocm720 runs-on: ubuntu-latest steps: diff --git a/.github/workflows/nightly-test-amd.yml b/.github/workflows/nightly-test-amd.yml index a222062f9..dc600a8af 100644 --- a/.github/workflows/nightly-test-amd.yml +++ b/.github/workflows/nightly-test-amd.yml @@ -32,9 +32,11 @@ on: - 'nightly-8-gpu-deepseek-v32' - 'nightly-8-gpu-deepseek-v32-mtp' - 'nightly-8-gpu-kimi-k25' + - 'nightly-8-gpu-qwen3-235b' - 'nightly-8-gpu-glm5' # MI35x jobs - 'nightly-test-1-gpu-mi35x' + - 'nightly-8-gpu-mi35x-qwen3-235b-mxfp4' - 'nightly-8-gpu-mi35x-kimi-k25' - 'nightly-8-gpu-mi35x-glm5' - 'nightly-accuracy-8-gpu-mi35x' @@ -496,6 +498,35 @@ jobs: echo "$(> $GITHUB_STEP_SUMMARY || true exit ${TEST_EXIT_CODE:-0} + nightly-8-gpu-qwen3-235b: + if: (github.repository == 'sgl-project/sglang' || github.event_name == 'pull_request') && (inputs.job_filter == '' || inputs.job_filter == 'all' || inputs.job_filter == 'nightly-8-gpu-qwen3-235b') + runs-on: linux-mi325-gpu-8 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref || github.ref }} + + - name: Setup docker + run: | + touch github_summary.md + bash scripts/ci/amd/amd_ci_start_container.sh + env: + GITHUB_WORKSPACE: ${{ github.workspace }} + + - name: Install dependencies + run: bash scripts/ci/amd/amd_ci_install_dependency.sh + + - name: Accuracy Test + Performance Test (8-GPU Qwen3) + timeout-minutes: 120 + run: | + > github_summary.md # Clear summary file + bash scripts/ci/amd/amd_ci_exec.sh -w /sglang-checkout/test \ + -e GITHUB_STEP_SUMMARY="/sglang-checkout/github_summary.md" \ + python3 run_suite.py --hw amd --suite nightly-8-gpu-qwen3-235b --nightly --timeout-per-file 3600 || TEST_EXIT_CODE=$? + echo "$(> $GITHUB_STEP_SUMMARY || true + exit ${TEST_EXIT_CODE:-0} + nightly-8-gpu-glm5: if: (github.repository == 'sgl-project/sglang' || github.event_name == 'pull_request') && (inputs.job_filter == '' || inputs.job_filter == 'all' || inputs.job_filter == 'nightly-8-gpu-glm5') runs-on: linux-mi325-gpu-8 @@ -861,6 +892,39 @@ jobs: echo "$(> $GITHUB_STEP_SUMMARY || true exit ${TEST_EXIT_CODE:-0} + # MI35x 8-GPU Qwen3-235B-MXFP4 (Accuracy + Performance) + nightly-8-gpu-mi35x-qwen3-235b-mxfp4: + if: (github.repository == 'sgl-project/sglang' || github.event_name == 'pull_request') && (inputs.job_filter == '' || inputs.job_filter == 'all' || inputs.job_filter == 'nightly-8-gpu-mi35x-qwen3-235b-mxfp4') + runs-on: linux-mi35x-gpu-8 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref || github.ref }} + + - name: Setup docker + run: | + touch github_summary.md + bash scripts/ci/amd/amd_ci_start_container.sh + env: + GITHUB_WORKSPACE: ${{ github.workspace }} + + - name: Install dependencies + run: | + bash scripts/ci/amd/amd_ci_install_dependency.sh + # Install tabulate for run_suite.py (missing in MI35x container) + bash scripts/ci/amd/amd_ci_exec.sh pip install tabulate + + - name: Accuracy Test + Performance Test MI35x (8-GPU Qwen3-235B-MXFP4) + timeout-minutes: 120 + run: | + > github_summary.md # Clear summary file + bash scripts/ci/amd/amd_ci_exec.sh -w /sglang-checkout/test \ + -e GITHUB_STEP_SUMMARY="/sglang-checkout/github_summary.md" \ + python3 run_suite.py --hw amd --suite nightly-8-gpu-mi35x-qwen3-235b-mxfp4 --nightly --timeout-per-file 3600 || TEST_EXIT_CODE=$? + echo "$(> $GITHUB_STEP_SUMMARY || true + exit ${TEST_EXIT_CODE:-0} + nightly-8-gpu-mi35x-glm5: if: (github.repository == 'sgl-project/sglang' || github.event_name == 'pull_request') && (inputs.job_filter == '' || inputs.job_filter == 'all' || inputs.job_filter == 'nightly-8-gpu-mi35x-glm5') runs-on: linux-mi35x-gpu-8 @@ -947,6 +1011,7 @@ jobs: - nightly-8-gpu-deepseek-v32 - nightly-8-gpu-deepseek-v32-mtp - nightly-8-gpu-kimi-k25 + - nightly-8-gpu-qwen3-235b - nightly-8-gpu-glm5 # MI35x jobs - nightly-test-1-gpu-mi35x @@ -957,6 +1022,7 @@ jobs: - nightly-accuracy-8-gpu-mi35x-deepseek-v32 - nightly-accuracy-8-gpu-mi35x-deepseek-v32-mtp - nightly-8-gpu-mi35x-kimi-k25 + - nightly-8-gpu-mi35x-qwen3-235b-mxfp4 - nightly-8-gpu-mi35x-glm5 # MI35x perf jobs excluded from check - perf failures don't block CI # - nightly-perf-8-gpu-mi35x-deepseek-v32-basic diff --git a/test/registered/amd/test_qwen3_instruct.py b/test/registered/amd/test_qwen3_instruct.py new file mode 100644 index 000000000..eacd1d74b --- /dev/null +++ b/test/registered/amd/test_qwen3_instruct.py @@ -0,0 +1,92 @@ +import os +import unittest +from types import SimpleNamespace + +import requests + +from sglang.srt.utils import kill_process_tree +from sglang.test.ci.ci_register import register_amd_ci +from sglang.test.few_shot_gsm8k import run_eval as run_eval_few_shot_gsm8k +from sglang.test.send_one import BenchArgs, send_one_prompt +from sglang.test.test_utils import ( + DEFAULT_URL_FOR_TEST, + CustomTestCase, + is_in_amd_ci, + is_in_ci, + popen_launch_server, + write_github_step_summary, +) + +register_amd_ci(est_time=3600, suite="nightly-8-gpu-qwen3-235b", nightly=True) + +QWEN3_MODEL_PATH = "Qwen/Qwen3-235B-A22B-Instruct-2507" +SERVER_LAUNCH_TIMEOUT = 3600 + + +class TestQwen3Instruct2507(CustomTestCase): + @classmethod + def setUpClass(cls): + cls.model = QWEN3_MODEL_PATH + cls.base_url = DEFAULT_URL_FOR_TEST + other_args = [ + "--tp", + "8", + "--trust-remote-code", + "--attention-backend", + "aiter", + ] + env = os.environ.copy() + env["SGLANG_USE_AITER"] = "1" + cls.process = popen_launch_server( + cls.model, + cls.base_url, + timeout=SERVER_LAUNCH_TIMEOUT, + other_args=other_args, + env=env, + ) + + @classmethod + def tearDownClass(cls): + kill_process_tree(cls.process.pid) + + def test_a_gsm8k( + self, + ): # Append an "a" to make this test run first (alphabetically) to warm up the server + requests.get(self.base_url + "/flush_cache") + + args = SimpleNamespace( + num_shots=8, + data_path=None, + num_questions=1319, + parallel=1319, + max_new_tokens=512, + host="http://127.0.0.1", + port=int(self.base_url.split(":")[-1]), + ) + metrics = run_eval_few_shot_gsm8k(args) + print(f"{metrics=}") + + if is_in_ci(): + write_github_step_summary( + f"### test_gsm8k ({self.model})\n" f'{metrics["accuracy"]=:.3f}\n' + ) + self.assertGreater(metrics["accuracy"], 0.95) + + def test_bs_1_speed(self): + args = BenchArgs(port=int(self.base_url.split(":")[-1]), max_new_tokens=2048) + _, speed = send_one_prompt(args) + + print(f"{speed=:.2f}") + + if is_in_ci(): + write_github_step_summary( + f"### test_bs_1_speed ({self.model})\n" f"{speed=:.2f} token/s\n" + ) + if is_in_amd_ci(): + self.assertGreater(speed, 50) + else: + self.assertGreater(speed, 75) + + +if __name__ == "__main__": + unittest.main() diff --git a/test/registered/amd/test_qwen3_instruct_fp8.py b/test/registered/amd/test_qwen3_instruct_fp8.py new file mode 100644 index 000000000..7c2978e2f --- /dev/null +++ b/test/registered/amd/test_qwen3_instruct_fp8.py @@ -0,0 +1,92 @@ +import os +import unittest +from types import SimpleNamespace + +import requests + +from sglang.srt.utils import kill_process_tree +from sglang.test.ci.ci_register import register_amd_ci +from sglang.test.few_shot_gsm8k import run_eval as run_eval_few_shot_gsm8k +from sglang.test.send_one import BenchArgs, send_one_prompt +from sglang.test.test_utils import ( + DEFAULT_URL_FOR_TEST, + CustomTestCase, + is_in_amd_ci, + is_in_ci, + popen_launch_server, + write_github_step_summary, +) + +register_amd_ci(est_time=3600, suite="nightly-8-gpu-qwen3-235b", nightly=True) + +QWEN3_MODEL_PATH = "Qwen/Qwen3-235B-A22B-Instruct-2507-FP8" +SERVER_LAUNCH_TIMEOUT = 3600 + + +class TestQwen3Instruct2507FP8(CustomTestCase): + @classmethod + def setUpClass(cls): + cls.model = QWEN3_MODEL_PATH + cls.base_url = DEFAULT_URL_FOR_TEST + other_args = [ + "--tp", + "4", + "--trust-remote-code", + "--attention-backend", + "aiter", + ] + env = os.environ.copy() + env["SGLANG_USE_AITER"] = "1" + cls.process = popen_launch_server( + cls.model, + cls.base_url, + timeout=SERVER_LAUNCH_TIMEOUT, + other_args=other_args, + env=env, + ) + + @classmethod + def tearDownClass(cls): + kill_process_tree(cls.process.pid) + + def test_a_gsm8k( + self, + ): # Append an "a" to make this test run first (alphabetically) to warm up the server + requests.get(self.base_url + "/flush_cache") + + args = SimpleNamespace( + num_shots=8, + data_path=None, + num_questions=1319, + parallel=1319, + max_new_tokens=512, + host="http://127.0.0.1", + port=int(self.base_url.split(":")[-1]), + ) + metrics = run_eval_few_shot_gsm8k(args) + print(f"{metrics=}") + + if is_in_ci(): + write_github_step_summary( + f"### test_gsm8k ({self.model})\n" f'{metrics["accuracy"]=:.3f}\n' + ) + self.assertGreater(metrics["accuracy"], 0.95) + + def test_bs_1_speed(self): + args = BenchArgs(port=int(self.base_url.split(":")[-1]), max_new_tokens=2048) + _, speed = send_one_prompt(args) + + print(f"{speed=:.2f}") + + if is_in_ci(): + write_github_step_summary( + f"### test_bs_1_speed ({self.model})\n" f"{speed=:.2f} token/s\n" + ) + if is_in_amd_ci(): + self.assertGreater(speed, 40) + else: + self.assertGreater(speed, 60) + + +if __name__ == "__main__": + unittest.main() diff --git a/test/registered/amd/test_qwen3_instruct_mxfp4.py b/test/registered/amd/test_qwen3_instruct_mxfp4.py new file mode 100644 index 000000000..f1e170946 --- /dev/null +++ b/test/registered/amd/test_qwen3_instruct_mxfp4.py @@ -0,0 +1,96 @@ +import os +import unittest +from types import SimpleNamespace + +import requests + +from sglang.srt.utils import kill_process_tree +from sglang.test.ci.ci_register import register_amd_ci +from sglang.test.few_shot_gsm8k import run_eval as run_eval_few_shot_gsm8k +from sglang.test.send_one import BenchArgs, send_one_prompt +from sglang.test.test_utils import ( + DEFAULT_URL_FOR_TEST, + CustomTestCase, + is_in_amd_ci, + is_in_ci, + popen_launch_server, + write_github_step_summary, +) + +register_amd_ci( + est_time=3600, suite="nightly-8-gpu-mi35x-qwen3-235b-mxfp4", nightly=True +) + +QWEN3_MODEL_PATH = "amd/Qwen3-235B-A22B-Instruct-2507-mxfp4" +SERVER_LAUNCH_TIMEOUT = 3600 + + +class TestQwen3Instruct2507MXFP4(CustomTestCase): + @classmethod + def setUpClass(cls): + cls.model = QWEN3_MODEL_PATH + cls.base_url = DEFAULT_URL_FOR_TEST + other_args = [ + "--tp", + "4", + "--ep", + "2", + "--trust-remote-code", + "--attention-backend", + "aiter", + ] + env = os.environ.copy() + env["SGLANG_USE_AITER"] = "1" + cls.process = popen_launch_server( + cls.model, + cls.base_url, + timeout=SERVER_LAUNCH_TIMEOUT, + other_args=other_args, + env=env, + ) + + @classmethod + def tearDownClass(cls): + kill_process_tree(cls.process.pid) + + def test_a_gsm8k( + self, + ): # Append an "a" to make this test run first (alphabetically) to warm up the server + requests.get(self.base_url + "/flush_cache") + + args = SimpleNamespace( + num_shots=8, + data_path=None, + num_questions=1319, + parallel=1319, + max_new_tokens=512, + host="http://127.0.0.1", + port=int(self.base_url.split(":")[-1]), + ) + metrics = run_eval_few_shot_gsm8k(args) + print(f"{metrics=}") + + if is_in_ci(): + write_github_step_summary( + f"### test_gsm8k ({self.model})\n" f'{metrics["accuracy"]=:.3f}\n' + ) + self.assertGreater(metrics["accuracy"], 0.93) + + def test_bs_1_speed(self): + args = BenchArgs(port=int(self.base_url.split(":")[-1]), max_new_tokens=2048) + _, speed = send_one_prompt(args) + + print(f"{speed=:.2f}") + + if is_in_ci(): + write_github_step_summary( + f"### test_bs_1_speed ({self.model})\n" f"{speed=:.2f} token/s\n" + ) + if is_in_amd_ci(): + self.assertGreater(speed, 60) + else: + self.assertGreater(speed, 90) + + +if __name__ == "__main__": + unittest.main()