-
-
Notifications
You must be signed in to change notification settings - Fork 19.3k
Tuning script and configs for Triton Mamba SSU kernel #43083
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 19 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
b92d438
[Mamba] selective_state_update auto-tuning framework with NVIDIA GB10…
bananighosh f7efdb8
Apply code review changes
danisereb a5e44cb
Use cache (same as lru_cache with maxsize None) for try_get_optimal_s…
danisereb e1db1d7
Add tuned JSON files for H100
danisereb 56a1928
Add CUDA graphs to script
danisereb 1dd1de1
Add tuned JSONs for H100
danisereb aa4ad6d
Remove ref to fused_moe, use cache instead of lru_cache
danisereb 35103b8
Remove duplicate functions from the tuning script
danisereb e77985f
Fix --validate failure
danisereb af47691
Reuse tuned measurements for comparisons
danisereb 702faaf
Add support for mamba cache bf16 (match to fp16 config)
danisereb c856e72
Add flags --batch-sizes and --nheads
danisereb 621137a
Move location of config files
danisereb 878de24
Use contextmanager for override_ssm_config
danisereb 24a2f61
Cleanup comments
danisereb e4c3181
Add upper limit to eff batch (to avoid cuda error)
danisereb 7337562
Update JSON for B200
danisereb 4953de9
Add tuned JSON files for GB200
danisereb 3c3f3aa
Update JSON for H100
danisereb 4bba278
Fix stale comment in get_ssm_config_file_name
danisereb e0152b2
Move selective_state_update_ref to new utils file
danisereb 7757ae5
Fix hard coded block_m/warps in test_mamba_ssm_configs
danisereb f01f9f1
Add more coverage in test_mamba_ssm_configs
danisereb f1b0f51
Update comment for VLLM_TUNED_CONFIG_FOLDER
danisereb File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,218 @@ | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # SPDX-FileCopyrightText: Copyright contributors to the vLLM project | ||
| """ | ||
| Unit tests for the JSON-based config loader added to selective_state_update. | ||
|
|
||
| Tests cover: | ||
| - Flat MoE-style filename generation | ||
| - VLLM_TUNED_CONFIG_FOLDER env-var override | ||
| - Fallback to heuristic when no config file exists | ||
| - Nearest effective_batch interpolation | ||
| - Edge cases: non-dict JSON, empty config | ||
| """ | ||
|
|
||
| import json | ||
|
|
||
| from vllm.model_executor.layers.mamba.ops.mamba_ssm import ( | ||
| _try_get_optimal_ssm_config_cached, | ||
| get_ssm_config_file_name, | ||
| get_ssm_configs, | ||
| get_ssm_device_name, | ||
| try_get_optimal_ssm_config, | ||
| ) | ||
|
|
||
| # Common kwargs for try_get_optimal_ssm_config. Tests pick (batch, nheads) so | ||
| # their product (effective_batch) matches the value being probed. | ||
| _HEADDIM = 64 | ||
| _CACHE_DTYPE = "float32" | ||
|
|
||
|
|
||
| def _clear_caches() -> None: | ||
| get_ssm_configs.cache_clear() | ||
| _try_get_optimal_ssm_config_cached.cache_clear() | ||
|
|
||
|
|
||
| def _write_config(tmp_path, dstate: int, payload: dict) -> None: | ||
| """Write payload as the bundled config for (headdim, dstate, cache_dtype).""" | ||
| device_name = get_ssm_device_name() | ||
| config_path = tmp_path / get_ssm_config_file_name( | ||
| _HEADDIM, dstate, _CACHE_DTYPE, device_name | ||
| ) | ||
| with open(config_path, "w") as f: | ||
| json.dump(payload, f) | ||
|
|
||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Config filename generation | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| def test_config_file_name_format(): | ||
| name = get_ssm_config_file_name( | ||
| headdim=64, dstate=128, cache_dtype="float32", device_name="NVIDIA_B200" | ||
| ) | ||
| assert name == ( | ||
| "headdim=64,dstate=128,device_name=NVIDIA_B200,cache_dtype=float32.json" | ||
| ) | ||
|
|
||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # VLLM_TUNED_CONFIG_FOLDER override | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| def test_env_override_loads_custom_config(monkeypatch, tmp_path): | ||
| """VLLM_TUNED_CONFIG_FOLDER should take precedence over the bundled dir.""" | ||
| _write_config( | ||
| tmp_path, | ||
| dstate=16, | ||
| payload={ | ||
| "1": {"BLOCK_SIZE_M": 4, "num_warps": 1}, | ||
| }, | ||
| ) | ||
|
|
||
| monkeypatch.setenv("VLLM_TUNED_CONFIG_FOLDER", str(tmp_path)) | ||
| _clear_caches() | ||
|
|
||
| cfg = get_ssm_configs(_HEADDIM, 16, _CACHE_DTYPE) | ||
| assert cfg is not None | ||
| assert cfg[1] == {"BLOCK_SIZE_M": 4, "num_warps": 1} | ||
|
|
||
| _clear_caches() | ||
|
|
||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Fallback to heuristic when no config file exists | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| def test_fallback_when_no_config(monkeypatch, tmp_path): | ||
| """try_get_optimal_ssm_config must fall back to the hard-coded heuristic | ||
| when no JSON file is found for the current device.""" | ||
| monkeypatch.setenv("VLLM_TUNED_CONFIG_FOLDER", str(tmp_path)) | ||
| monkeypatch.setattr( | ||
| "vllm.model_executor.layers.mamba.ops.mamba_ssm._CONFIGS_DIR", | ||
| str(tmp_path), | ||
| ) | ||
| _clear_caches() | ||
|
|
||
| # dstate=64 heuristic: BLOCK_SIZE_M=8, num_warps=4 | ||
| block_m, warps = try_get_optimal_ssm_config( | ||
| headdim=_HEADDIM, | ||
| dstate=64, | ||
| batch=1, | ||
| nheads=1, | ||
| cache_dtype=_CACHE_DTYPE, | ||
| is_blackwell=False, | ||
| ) | ||
| assert block_m == 8 | ||
| assert warps == 4 | ||
|
|
||
| # dstate=16 heuristic: BLOCK_SIZE_M=32, num_warps=4 | ||
| block_m, warps = try_get_optimal_ssm_config( | ||
| headdim=_HEADDIM, | ||
| dstate=16, | ||
| batch=1, | ||
| nheads=1, | ||
| cache_dtype=_CACHE_DTYPE, | ||
| is_blackwell=False, | ||
| ) | ||
| assert block_m == 32 | ||
| assert warps == 4 | ||
|
|
||
| _clear_caches() | ||
|
|
||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Nearest effective_batch interpolation | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| def test_nearest_effective_batch_interpolation(monkeypatch, tmp_path): | ||
| """When effective_batch = batch*nheads is not an exact key, the closest | ||
| key should be selected.""" | ||
| _write_config( | ||
| tmp_path, | ||
| dstate=32, | ||
| payload={ | ||
| "64": {"BLOCK_SIZE_M": 8, "num_warps": 1}, | ||
| "4096": {"BLOCK_SIZE_M": 32, "num_warps": 4}, | ||
| }, | ||
| ) | ||
|
|
||
| monkeypatch.setenv("VLLM_TUNED_CONFIG_FOLDER", str(tmp_path)) | ||
| _clear_caches() | ||
|
|
||
| # effective_batch = 1*128 = 128 -> closer to 64 than to 4096 | ||
| block_m, warps = try_get_optimal_ssm_config( | ||
| headdim=_HEADDIM, | ||
| dstate=32, | ||
| batch=1, | ||
| nheads=128, | ||
| cache_dtype=_CACHE_DTYPE, | ||
| is_blackwell=False, | ||
| ) | ||
| assert block_m == 8 and warps == 1 | ||
|
|
||
| # effective_batch = 4*1024 = 4096 -> exact match on 4096 | ||
| block_m, warps = try_get_optimal_ssm_config( | ||
| headdim=_HEADDIM, | ||
| dstate=32, | ||
| batch=4, | ||
| nheads=1024, | ||
| cache_dtype=_CACHE_DTYPE, | ||
| is_blackwell=False, | ||
| ) | ||
| assert block_m == 32 and warps == 4 | ||
|
|
||
| _clear_caches() | ||
|
|
||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Edge cases: malformed / empty config files | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| def test_non_dict_json_returns_none(monkeypatch, tmp_path): | ||
| """A valid JSON file that is not a dict (e.g. a list) must be ignored | ||
| and return None rather than raising AttributeError.""" | ||
| device_name = get_ssm_device_name() | ||
| config_path = tmp_path / get_ssm_config_file_name( | ||
| _HEADDIM, 16, _CACHE_DTYPE, device_name | ||
| ) | ||
| with open(config_path, "w") as f: | ||
| json.dump([1, 2, 3], f) | ||
|
|
||
| monkeypatch.setenv("VLLM_TUNED_CONFIG_FOLDER", str(tmp_path)) | ||
| monkeypatch.setattr( | ||
| "vllm.model_executor.layers.mamba.ops.mamba_ssm._CONFIGS_DIR", | ||
| str(tmp_path), | ||
| ) | ||
| _clear_caches() | ||
|
|
||
| assert get_ssm_configs(_HEADDIM, 16, _CACHE_DTYPE) is None | ||
|
|
||
| _clear_caches() | ||
|
|
||
|
|
||
| def test_empty_config_falls_back_to_heuristic(monkeypatch, tmp_path): | ||
| """An empty JSON object {} must not crash min() — should fall back | ||
| to the hard-coded heuristic.""" | ||
| _write_config(tmp_path, dstate=64, payload={}) | ||
|
|
||
| monkeypatch.setenv("VLLM_TUNED_CONFIG_FOLDER", str(tmp_path)) | ||
| _clear_caches() | ||
|
|
||
| # dstate=64 heuristic: BLOCK_SIZE_M=8, num_warps=4 | ||
| block_m, warps = try_get_optimal_ssm_config( | ||
| headdim=_HEADDIM, | ||
| dstate=64, | ||
| batch=1, | ||
| nheads=64, | ||
| cache_dtype=_CACHE_DTYPE, | ||
| is_blackwell=False, | ||
| ) | ||
| assert block_m == 8 | ||
| assert warps == 4 | ||
|
|
||
| _clear_caches() | ||
87 changes: 87 additions & 0 deletions
87
...ctive_state_update/headdim=64,dstate=128,device_name=NVIDIA_B200,cache_dtype=float16.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| { | ||
| "triton_version": "3.6.0", | ||
| "8": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 4 | ||
| }, | ||
| "16": { | ||
| "BLOCK_SIZE_M": 8, | ||
| "num_warps": 8 | ||
| }, | ||
| "32": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "64": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 4 | ||
| }, | ||
| "128": { | ||
| "BLOCK_SIZE_M": 32, | ||
| "num_warps": 4 | ||
| }, | ||
| "256": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| }, | ||
| "512": { | ||
| "BLOCK_SIZE_M": 32, | ||
| "num_warps": 4 | ||
| }, | ||
| "1024": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| }, | ||
| "2048": { | ||
| "BLOCK_SIZE_M": 32, | ||
| "num_warps": 2 | ||
| }, | ||
| "4096": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| }, | ||
| "8192": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| }, | ||
| "12288": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| }, | ||
| "16384": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| }, | ||
| "24576": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| }, | ||
| "32768": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| }, | ||
| "49152": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| }, | ||
| "65536": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| }, | ||
| "98304": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| }, | ||
| "131072": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| }, | ||
| "196608": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| }, | ||
| "262144": { | ||
| "BLOCK_SIZE_M": 16, | ||
| "num_warps": 2 | ||
| } | ||
| } |
87 changes: 87 additions & 0 deletions
87
...ctive_state_update/headdim=64,dstate=128,device_name=NVIDIA_B200,cache_dtype=float32.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| { | ||
| "triton_version": "3.6.0", | ||
| "8": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 4 | ||
| }, | ||
| "16": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "32": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "64": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "128": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "256": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "512": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "1024": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "2048": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "4096": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "8192": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "12288": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "16384": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "24576": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "32768": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "49152": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "65536": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "98304": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "131072": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "196608": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| }, | ||
| "262144": { | ||
| "BLOCK_SIZE_M": 4, | ||
| "num_warps": 1 | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the test should get the heuristic from the code, not hard-code it again. Current code breaks if heuristic changes / if it runs on different hardware where heuristic is different
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done