-
Notifications
You must be signed in to change notification settings - Fork 2.7k
[https://nvbugs/6700677][fix] Fix Gemma4 startup on non-SM100 GPUs #18547
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
base: main
Are you sure you want to change the base?
Changes from all commits
e200c9f
165f397
a7704cc
7a7715b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,7 @@ | |
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| import dataclasses | ||
| from typing import List, Optional, Sequence | ||
| from typing import List, Optional, Protocol, Sequence, Union, cast | ||
|
|
||
| import torch | ||
| import transformers | ||
|
|
@@ -11,6 +11,26 @@ | |
| from tensorrt_llm.llmapi.llm_args import CacheTransceiverConfig | ||
| from tensorrt_llm.logger import logger | ||
|
|
||
| _GEMMA4_TEXT_MODEL_TYPES = {"gemma4_text", "gemma4_unified_text"} | ||
|
|
||
|
|
||
| class _NamedLayerType(Protocol): | ||
| name: str | ||
|
|
||
|
|
||
| _LayerType = Union[str, _NamedLayerType] | ||
|
|
||
|
|
||
| class _Gemma4LayerGeometry(Protocol): | ||
| head_dim: int | ||
| num_key_value_heads: int | ||
|
|
||
|
|
||
| class _Gemma4GeometryConfig(Protocol): | ||
| head_dim: int | ||
| num_key_value_heads: int | ||
| layer_types: Sequence[_LayerType] | ||
|
|
||
|
|
||
| def resolve_cache_transceiver_config( | ||
| cache_transceiver_config: Optional[CacheTransceiverConfig]) -> None: | ||
|
|
@@ -71,12 +91,52 @@ def uses_vswa_kv_cache_layout( | |
| for window in max_attention_windows)) | ||
|
|
||
|
|
||
| def _is_sliding_attention_layer(layer_type: object) -> bool: | ||
| def _is_sliding_attention_layer(layer_type: _LayerType) -> bool: | ||
| """Return whether a config layer type denotes sliding attention.""" | ||
| layer_type_name = getattr(layer_type, "name", str(layer_type)).lower() | ||
| return "sliding" in layer_type_name | ||
|
|
||
|
|
||
| def _get_gemma4_per_layer_config( | ||
| config: _Gemma4GeometryConfig, | ||
| layer_idx: int, | ||
| ) -> Optional[_Gemma4LayerGeometry]: | ||
| """Return a concrete Gemma4 layer config when Transformers provides one.""" | ||
| per_layer_config = getattr(config, "per_layer_config", None) | ||
| if per_layer_config is None: | ||
| return None | ||
| return cast(Sequence[_Gemma4LayerGeometry], per_layer_config)[layer_idx] | ||
|
|
||
|
|
||
| def get_gemma4_layer_head_dim(config: _Gemma4GeometryConfig, | ||
| layer_idx: int) -> int: | ||
| """Return Gemma4's head dimension for one layer across HF config schemas.""" | ||
| layer_config = _get_gemma4_per_layer_config(config, layer_idx) | ||
| if layer_config is not None: | ||
| return layer_config.head_dim | ||
|
|
||
| head_dim = config.head_dim | ||
| if _is_sliding_attention_layer(config.layer_types[layer_idx]): | ||
| return head_dim | ||
| global_head_dim = getattr(config, "global_head_dim", None) | ||
| return global_head_dim if global_head_dim is not None else head_dim | ||
|
|
||
|
|
||
| def get_gemma4_layer_num_kv_heads(config: _Gemma4GeometryConfig, | ||
| layer_idx: int) -> int: | ||
| """Return Gemma4's KV-head count for one layer across HF config schemas.""" | ||
| layer_config = _get_gemma4_per_layer_config(config, layer_idx) | ||
| if layer_config is not None: | ||
| return layer_config.num_key_value_heads | ||
|
|
||
| num_kv_heads = config.num_key_value_heads | ||
| is_sliding = _is_sliding_attention_layer(config.layer_types[layer_idx]) | ||
| if not is_sliding and getattr(config, "attention_k_eq_v", False): | ||
| return getattr(config, "num_global_key_value_heads", | ||
| None) or num_kv_heads | ||
| return num_kv_heads | ||
|
|
||
|
|
||
| def get_layer_attention_window( | ||
| config: object, | ||
| layer_idx: int, | ||
|
|
@@ -124,7 +184,16 @@ def get_layer_attention_window( | |
|
|
||
|
|
||
| def is_gemma4_hybrid(config): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win Add complete annotations to
As per coding guidelines, “Annotate every function” and “use precise types instead of 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
| """True for Gemma4 models with hybrid attention (different head_dim per layer type).""" | ||
| """True when Gemma4 requires per-layer attention geometry.""" | ||
| model_type = str(getattr(config, "model_type", "")).lower() | ||
| if model_type not in _GEMMA4_TEXT_MODEL_TYPES: | ||
| return False | ||
|
|
||
| per_layer_attributes = getattr(config, "per_layer_attributes", None) | ||
| if per_layer_attributes is not None: | ||
| return not {"head_dim", "num_key_value_heads" | ||
| }.isdisjoint(per_layer_attributes) | ||
|
|
||
| global_head_dim = getattr(config, 'global_head_dim', None) | ||
| head_dim = getattr(config, 'head_dim', None) | ||
| return (global_head_dim is not None and isinstance(head_dim, int) | ||
|
|
||
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.
Two nits on this fallback path: (1)
next()without a default raises a bareStopIterationiflayer_typescontains no layer matchingis_sliding— pass a sentinel and raise a clear ValueError instead. (2) The guard above checksper_layer_attributeswhile the geometry helpers key offper_layer_config(_get_gemma4_per_layer_config); a config withper_layer_configbut no/emptyper_layer_attributesslips past the guard and silently resolves geometry from whichever layer of that type comes first. Gating onper_layer_configtoo keeps the error condition aligned with what the helpers actually consume.