Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
f438a2e
kernel native
Cyrilvallez Jul 13, 2026
7c1335b
fix warning
Cyrilvallez Jul 13, 2026
f8ff0db
have to fix other modular to be coherent
Cyrilvallez Jul 13, 2026
9a8127e
remove useless
Cyrilvallez Jul 13, 2026
72b45ca
use native lib as well
Cyrilvallez Jul 13, 2026
54d80df
modular
Cyrilvallez Jul 13, 2026
d2beaf6
combine them
Cyrilvallez Jul 13, 2026
c256c47
doc
Cyrilvallez Jul 13, 2026
30e0ff7
ignore kwargs, allow og
vasqu Jul 13, 2026
c57b520
Merge remote-tracking branch 'upstream/main' into kernels-fallback
vasqu Jul 29, 2026
38c2ece
fix
vasqu Jul 29, 2026
7788cac
gdn like paths (missing conv of olmo hybrid)
vasqu Jul 29, 2026
cf49de6
olmo hybrid fused conv style
vasqu Jul 29, 2026
73db89b
fix
vasqu Jul 29, 2026
8896696
fix
vasqu Jul 29, 2026
d3b27a6
poc mamba2, kernel must compile but torch seems to match
vasqu Jul 29, 2026
f0aa581
kernels match --> hf kernels will be needed
vasqu Jul 29, 2026
263f307
style
vasqu Jul 29, 2026
a189da9
quick fixes
vasqu Jul 30, 2026
8134d38
Merge remote-tracking branch 'upstream/main' into kernels-fallback
vasqu Jul 30, 2026
4ebeb11
mamba2 works
vasqu Jul 30, 2026
1786c75
mamba2 suite of models
vasqu Jul 30, 2026
0eca0d0
oops
vasqu Jul 30, 2026
82bfade
conv1ds across other models
vasqu Jul 30, 2026
520e340
let's try this
vasqu Jul 30, 2026
f69acfe
mamba base implementation
vasqu Jul 30, 2026
bfbf9f1
fixups as per review comments
vasqu Aug 3, 2026
511d4a6
fixup mamba tests and other issues
vasqu Aug 3, 2026
3ee52c3
make no shape check by default (single padded sample should also work)
vasqu Aug 3, 2026
34051c4
remove todo
vasqu Aug 3, 2026
c3a6c98
propogate mamba1
vasqu Aug 3, 2026
fcf7292
style
vasqu Aug 3, 2026
3823bcb
fix mambapy + enable on jamba
vasqu Aug 3, 2026
380e5fc
zamba1
vasqu Aug 3, 2026
ad78e09
style
vasqu Aug 3, 2026
3c51e11
fix early cast (leads to non fp32 norm)
vasqu Aug 3, 2026
b05fb52
fix padding free path
vasqu Aug 3, 2026
98f62d4
fix offload
vasqu Aug 3, 2026
66cff33
Merge remote-tracking branch 'upstream/main' into kernels-fallback
vasqu Aug 3, 2026
2ec940b
Merge remote-tracking branch 'upstream/main' into kernels-fallback
vasqu Aug 4, 2026
9b266aa
bump kernels
vasqu Aug 4, 2026
c4b785c
remove todo
vasqu Aug 4, 2026
c85e622
avoid onnx export and fix mamba2 test
vasqu Aug 4, 2026
2b4fd75
fix bamba test
vasqu Aug 4, 2026
2e485f3
update falcon mamba - aligned with all other devices
vasqu Aug 4, 2026
d81829f
oops
vasqu Aug 4, 2026
95a2954
kernels=True by default
vasqu Aug 4, 2026
fc9ce38
Merge remote-tracking branch 'upstream/main' into default-kernels
vasqu Aug 4, 2026
85f30d1
fixup tests that require kernels (at model load time)
vasqu Aug 4, 2026
7e7b621
let's apply kernels where we can! only on non inherited classes ignor…
vasqu Aug 4, 2026
eac7ad9
moe
vasqu Aug 4, 2026
690ca05
style
vasqu Aug 4, 2026
2a1ab0c
oops
vasqu Aug 4, 2026
6e4e009
fix offline (disable in any case), fix run kernels to use prepared pe…
vasqu Aug 4, 2026
13a57cd
test
vasqu Aug 4, 2026
b30a5e8
fix
vasqu Aug 4, 2026
01fc01d
let's make them also inherit as special cases
vasqu Aug 4, 2026
dac48c5
Merge branch 'main' into default-kernels
vasqu Aug 4, 2026
2b31778
come ooon
vasqu Aug 4, 2026
a1dc96f
kernels is default install
vasqu Aug 4, 2026
e203afa
forgot that one
vasqu Aug 4, 2026
52887a3
add todo
vasqu Aug 4, 2026
2cbd4b2
fix versioning for newer torch
vasqu Aug 4, 2026
32c5bcf
Merge branch 'main' into default-kernels
vasqu Aug 4, 2026
1fd733d
Merge branch 'main' into default-kernels
ydshieh Aug 5, 2026
7848351
Merge remote-tracking branch 'upstream/main' into default-kernels
vasqu Aug 5, 2026
b82d8ff
it got duplicated
vasqu Aug 5, 2026
fa78aaf
Merge branch 'main' into default-kernels
ydshieh Aug 5, 2026
e37810b
Merge branch 'main' into default-kernels
ydshieh Aug 5, 2026
b6021c4
at least push this
vasqu Aug 5, 2026
e8b0430
yes yes
vasqu Aug 5, 2026
6baa706
Merge branch 'main' into default-kernels
vasqu Sep 1, 2026
50019a8
initial implementation to reset kernelization
vasqu Sep 1, 2026
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
33 changes: 32 additions & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import _pytest
import pytest

from transformers import PreTrainedModel
from transformers.testing_utils import (
HfDoctestModule,
HfDocTestParser,
Expand All @@ -39,7 +40,7 @@
patch_testing_methods_to_collect_info,
patch_torch_compile_force_graph,
)
from transformers.utils import enable_tf32
from transformers.utils import ENV_VARS_TRUE_VALUES, enable_tf32
from transformers.utils.network_logging import register_network_debug_plugin


Expand Down Expand Up @@ -213,6 +214,10 @@ def wrapper(*args, **kwargs):
# they become normal warnings - i.e. the tests still need to test the current functionality
warnings.simplefilter(action="ignore", category=FutureWarning)

# we patch `from_pretrained` temporarily to be controlled via env variables
_from_pretrained_kernels_patch = None
_original_from_pretrained = PreTrainedModel.from_pretrained.__func__


def pytest_configure(config):
# Shared directory for the read-only cache fallback events. The controller creates it and
Expand Down Expand Up @@ -298,6 +303,32 @@ def pytest_configure(config):
os.environ["DISABLE_SAFETENSORS_CONVERSION"] = "true"
register_network_debug_plugin(config)

# Kernels related patching
global _from_pretrained_kernels_patch, _original_from_pretrained
os.environ["USE_HUB_KERNELS"] = "0" # Disable kernels for tests by default

@classmethod
def from_pretrained(cls, *args, **kwargs):
# Manipulate default as per env variables
kwargs.setdefault("use_kernels", os.environ.get("USE_HUB_KERNELS", "NO").upper() in ENV_VARS_TRUE_VALUES)
return _original_from_pretrained(cls, *args, **kwargs)

_from_pretrained_kernels_patch = mock.patch.object(
PreTrainedModel,
"from_pretrained",
from_pretrained,
)
_from_pretrained_kernels_patch.start()


def pytest_unconfigure(config):
# Disable default kwargs per env for kernels activation
global _from_pretrained_kernels_patch

if _from_pretrained_kernels_patch is not None:
_from_pretrained_kernels_patch.stop()
_from_pretrained_kernels_patch = None


def pytest_collection_modifyitems(items):
for item in items:
Expand Down
3 changes: 0 additions & 3 deletions docker/transformers-all-latest-gpu/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,6 @@ RUN python3 -m pip install --no-cache-dir einops
# For `VibeVoice` (added in PR #40546)
RUN python3 -m pip install --no-cache-dir diffusers

# `kernels` may give different outputs (within 1e-5 range) even with the same model (weights) and the same inputs
RUN python3 -m pip uninstall -y kernels

# When installing in editable mode, `transformers` is not recognized as a package.
# this line must be added in order for python to be aware of transformers.
RUN cd transformers && python3 setup.py develop
Expand Down
3 changes: 0 additions & 3 deletions docker/transformers-pytorch-amd-gpu/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ RUN cd transformers && python3 setup.py develop
# Remove nvml and nvidia-ml-py as it is not compatible with ROCm. apex is not tested on NVIDIA either.
RUN python3 -m pip uninstall py3nvml pynvml nvidia-ml-py apex -y

# `kernels` may causes many failing tests
RUN python3 -m pip uninstall -y kernels

# On ROCm, torchcodec is required to decode audio files. 0.10 matches the
# torch 2.10 C++ ABI in the base image above;
RUN python3 -m pip install --no-cache-dir "torchcodec==0.10"
Expand Down
3 changes: 0 additions & 3 deletions docker/transformers-pytorch-deepspeed-amd-gpu/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,3 @@ RUN python3 -c "from deepspeed.launcher.runner import main"

# Remove nvml as it is not compatible with ROCm
RUN python3 -m pip uninstall py3nvml pynvml nvidia-ml-py apex -y

# `kernels` may causes many failing tests
RUN python3 -m pip uninstall -y kernels
3 changes: 0 additions & 3 deletions docker/transformers-pytorch-deepspeed-latest-gpu/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ RUN python3 -m pip uninstall -y deepspeed
# TODO: Find out why test fail.
RUN DS_BUILD_CPU_ADAM=1 DS_BUILD_FUSED_ADAM=1 python3 -m pip install deepspeed --no-build-isolation --config-settings="--build-option=build_ext" --config-settings="--build-option=-j8" --no-cache -v --disable-pip-version-check 2>&1

# `kernels` may give different outputs (within 1e-5 range) even with the same model (weights) and the same inputs
RUN python3 -m pip uninstall -y kernels

# When installing in editable mode, `transformers` is not recognized as a package.
# this line must be added in order for python to be aware of transformers.
RUN cd transformers && python3 setup.py develop
Expand Down
3 changes: 0 additions & 3 deletions docker/transformers-pytorch-deepspeed-nightly-gpu/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ RUN python3 -m pip uninstall -y deepspeed
#RUN git clone https://github.com/pytorch/TensorRT.git
#RUN cd TensorRT/py && python3 setup.py install --fx-only

# `kernels` may give different outputs (within 1e-5 range) even with the same model (weights) and the same inputs
RUN python3 -m pip uninstall -y kernels

# When installing in editable mode, `transformers` is not recognized as a package.
# this line must be added in order for python to be aware of transformers.
RUN cd transformers && python3 setup.py develop
Expand Down
3 changes: 0 additions & 3 deletions docker/transformers-pytorch-gpu/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ RUN [ ${#TORCH_AUDIO} -gt 0 ] && VERSION='torchaudio=='TORCH_AUDIO'.*' || VERSI
RUN python3 -m pip install --no-cache-dir git+https://github.com/facebookresearch/detectron2.git pytesseract
RUN python3 -m pip install -U "itsdangerous<2.1.0"

# `kernels` may give different outputs (within 1e-5 range) even with the same model (weights) and the same inputs
RUN python3 -m pip uninstall -y kernels

# When installing in editable mode, `transformers` is not recognized as a package.
# this line must be added in order for python to be aware of transformers.
RUN cd transformers && python3 setup.py develop
3 changes: 0 additions & 3 deletions docker/transformers-quantization-latest-gpu/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,6 @@ RUN python3 -m pip install --no-cache-dir torchao
# Add transformers in editable mode
RUN python3 -m pip install --no-cache-dir -e ./transformers[dev]

# `kernels` may give different outputs (within 1e-5 range) even with the same model (weights) and the same inputs
RUN python3 -m pip uninstall -y kernels

# Uninstall flash-attn installed by autoawq, it causes issues here : https://github.com/huggingface/transformers/actions/runs/15915442841/job/44892146131
RUN python3 -m pip uninstall -y flash-attn

Expand Down
4 changes: 1 addition & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def deps_list(*pkgs):

extras = {}

extras["torch"] = deps_list("torch", "accelerate")
extras["torch"] = deps_list("torch", "accelerate", "kernels")
extras["vision"] = deps_list("torchvision", "Pillow")
extras["audio"] = deps_list("torchaudio", "librosa", "pyctcdecode", "phonemizer")
if PYTHON_MINOR_VERSION < 13:
Expand All @@ -186,7 +186,6 @@ def deps_list(*pkgs):
"datasets", "ruff", "GitPython", "urllib3", "libcst", "rich", "ty", "tomli", "transformers-mlinter"
)
extras["docs"] = deps_list("hf-doc-builder")
extras["kernels"] = deps_list("kernels")
extras["sentencepiece"] = deps_list("sentencepiece", "protobuf")
extras["tiktoken"] = deps_list("tiktoken", "blobfile")
extras["mistral-common"] = deps_list("mistral-common[image]")
Expand Down Expand Up @@ -249,7 +248,6 @@ def deps_list(*pkgs):
+ extras["vision"]
+ extras["audio"]
+ extras["video"]
+ extras["kernels"]
+ extras["timm"]
+ extras["sentencepiece"]
+ extras["tiktoken"]
Expand Down
24 changes: 24 additions & 0 deletions src/transformers/integrations/accelerate.py
Original file line number Diff line number Diff line change
Expand Up @@ -1021,3 +1021,27 @@ def wrapped(self, *args, **kwargs):
return wrapped

return decorator


def device_map_uses_accelerator(device_map: dict | str | int | None) -> bool:
"""Detect whether the device map contains any non-cpu device"""
if device_map is None:
return False

# Single device
if not isinstance(device_map, dict):
if isinstance(device_map, int):
return True
device = torch.device(device_map)
return device.type not in {"cpu", "meta"}

# Multi device
for target in device_map.values():
if target == "disk":
continue
if isinstance(target, int):
return True
if torch.device(target).type not in {"cpu", "meta"}:
return True

return False
89 changes: 34 additions & 55 deletions src/transformers/integrations/hub_kernels.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
from contextlib import contextmanager
from pathlib import Path
from types import ModuleType
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Optional

from ..conversion_mapping import get_checkpoint_conversion_mapping, register_checkpoint_conversion_mapping
from ..modeling_flash_attention_utils import FLASH_ATTN_KERNEL_VERSIONS
from ..monkey_patching import register_patch_mapping
from ..utils import ENV_VARS_TRUE_VALUES, logging
from ..utils.generic import is_flash_attention_requested
from ..utils.import_utils import (
KERNELS_MAX_VERSION,
KERNELS_MIN_VERSION,
Expand Down Expand Up @@ -58,8 +58,17 @@
)


_TRANSFORMERS_USE_HUB_KERNELS = os.environ.get("USE_HUB_KERNELS", "YES").upper()
_kernels_enabled = _TRANSFORMERS_USE_HUB_KERNELS in ENV_VARS_TRUE_VALUES
def _kernels_enabled() -> bool:
return os.environ.get("USE_HUB_KERNELS", "YES").upper() in ENV_VARS_TRUE_VALUES


def _ensure_kernels_enabled() -> None:
if not _kernels_enabled():
value = os.environ.get("USE_HUB_KERNELS", "YES")
raise ValueError(
"Hub kernels are disabled through the environment variable "
f"`USE_HUB_KERNELS={value}`. Set `USE_HUB_KERNELS=YES` to enable them."
)


# Maps from func name to the internal module path
Expand Down Expand Up @@ -98,37 +107,21 @@
)
from kernels import use_kernelized_func as _kernels_use_kernelized_func

# We change the strategy to prepare the metadata like kernels but the exchange
# at runtime can be determined by the env variable `USE_HUB_KERNELS`
def use_kernel_forward_from_hub(layer_name: str):
if _kernels_enabled:
return _kernels_use_kernel_forward_from_hub(layer_name)
else:
logger.warning_once(
f"kernels hub usage is disabled through the environment USE_HUB_KERNELS={_TRANSFORMERS_USE_HUB_KERNELS}"
)
return lambda cls: cls
return _kernels_use_kernel_forward_from_hub(layer_name)

def use_kernelized_func(module_names: list[Callable] | Callable):
if _kernels_enabled:
if isinstance(module_names, Callable):
module_names = [module_names]
return _kernels_use_kernelized_func(*module_names)
else:
logger.warning_once(
f"kernels hub usage is disabled through the environment USE_HUB_KERNELS={_TRANSFORMERS_USE_HUB_KERNELS}"
)
return lambda cls: cls
if isinstance(module_names, Callable):
module_names = [module_names]
return _kernels_use_kernelized_func(*module_names)

def use_kernel_func_from_hub(layer_name: str):
if _kernels_enabled:
logger.warning_once(
"`use_kernel_func_from_hub` is deprecated in transformers v5.16 and will be removed in the future. Please use `use_kernel_forward_from_hub` instead."
)
return _kernels_use_kernel_forward_from_hub(layer_name)
else:
logger.warning_once(
f"kernels hub usage is disabled through the environment USE_HUB_KERNELS={_TRANSFORMERS_USE_HUB_KERNELS}"
)
return lambda cls: cls
logger.warning_once(
"`use_kernel_func_from_hub` is deprecated in transformers v5.16 and will be removed in the future. Please use `use_kernel_forward_from_hub` instead."
)
return _kernels_use_kernel_forward_from_hub(layer_name)

# The default kernel mapping is built lazily (see `get_kernel_mapping_transformers`) so that simply
# importing transformers (or `transformers.pipeline`) does not instantiate any `LayerRepository` /
Expand Down Expand Up @@ -556,14 +549,13 @@ def get_kernel_mapping_transformers() -> dict:
return _KERNEL_MAPPING_CACHE

def register_kernel_mapping_transformers(mapping=None):
_ensure_kernels_enabled()
if mapping is None:
mapping = get_kernel_mapping_transformers()
register_kernel_mapping(mapping)

else:
_kernels_enabled = False

# Stub to make decorators in transformers work when `kernels`
# Stub to make decorators int transformers work when `kernels`
# is not installed.
def use_kernel_forward_from_hub(*args, **kwargs):
def decorator(cls):
Expand Down Expand Up @@ -624,16 +616,6 @@ def register_kernel_mapping_transformers(*args, **kwargs):
"nvfp4": {"repo_id": "kernels-community/nvfp4-gemm", "version": 1},
}

# Flash attention version -> major version of its hub kernel repo. Flash attention flavors that are not
# listed here, and all other attention kernels, use `_DEFAULT_ATTN_KERNEL_VERSION`.
_FLASH_ATTN_KERNEL_VERSION_MAPPING: dict[int, int] = {
# v3 is the first version shipping the Torch stable ABI (CUDA/ROCm) and Torch 2.13 builds (incl. XPU)
2: 3,
# FA4 is still in beta -> only v0 has been released
4: 0,
}
_DEFAULT_ATTN_KERNEL_VERSION = 1

_KERNEL_MODULE_MAPPING: dict[str, ModuleType | None] = {}


Expand All @@ -647,10 +629,7 @@ def is_kernel(attn_implementation: str | None) -> bool:

def get_attn_kernel_version(repo_id: str) -> int:
"""Return the major version of the hub kernel repo `repo_id` to load, e.g. `3` for `kernels-community/flash-attn2`."""
for flash_attn_version, kernel_version in _FLASH_ATTN_KERNEL_VERSION_MAPPING.items():
if is_flash_attention_requested(requested_attention_implementation=repo_id, version=flash_attn_version):
return kernel_version
return _DEFAULT_ATTN_KERNEL_VERSION
return FLASH_ATTN_KERNEL_VERSIONS.get(repo_id, 1)


def load_and_register_attn_kernel(
Expand Down Expand Up @@ -692,9 +671,7 @@ def load_and_register_attn_kernel(

# create revision xor version
rev = rev.strip() if rev else None
version = None
if rev is None:
version = get_attn_kernel_version(repo_id)
version = get_attn_kernel_version(repo_id) if rev is None else None

# Load the kernel from hub
try:
Expand Down Expand Up @@ -736,7 +713,7 @@ def lazy_load_kernel(kernel_name: str, mapping: dict[str, ModuleType | None] = _
logger.warning_once(f"Kernel {kernel_name} not found in _HUB_KERNEL_MAPPING")
mapping[kernel_name] = None
return None
if is_kernels_available() and _kernels_enabled:
if is_kernels_available() and _kernels_enabled():
try:
repo_id = _HUB_KERNEL_MAPPING[kernel_name]["repo_id"]
revision = _HUB_KERNEL_MAPPING[kernel_name].get("revision", None)
Expand Down Expand Up @@ -779,10 +756,11 @@ def lazy_load_kernel(kernel_name: str, mapping: dict[str, ModuleType | None] = _
return mapping[kernel_name]


def kernelize(model: "PreTrainedModel", mode: "Mode | None" = None):
def kernelize(model: "PreTrainedModel", mode: "Mode | None" = None, kernel_config: Optional["KernelConfig"] = None):
"""Temporarily register hidden kernel wrappers so `kernelize` can discover and replace them."""
if not is_kernels_available():
raise ImportError(_MISSING_KERNELS_MESSAGE)
_ensure_kernels_enabled()

def get_device(device_type):
if device_type == "cuda" and is_rocm_platform():
Expand All @@ -792,9 +770,10 @@ def get_device(device_type):
mode = Mode.INFERENCE if not model.training else Mode.TRAINING if mode is None else mode
device = get_device(model.device.type)

if model.kernel_config is not None:
inherit_mapping = not model.kernel_config.use_local_kernel
with use_kernel_mapping(model.kernel_config.kernel_mapping, inherit_mapping=inherit_mapping):
used_kernel_config = kernel_config or model.kernel_config
if used_kernel_config is not None:
inherit_mapping = not used_kernel_config.use_local_kernel and used_kernel_config.inherit_mapping
with use_kernel_mapping(used_kernel_config.kernel_mapping, inherit_mapping=inherit_mapping):
_kernels_kernelize(model, device=device, mode=mode)
else:
_kernels_kernelize(model, device=device, mode=mode)
Expand Down
8 changes: 8 additions & 0 deletions src/transformers/modeling_flash_attention_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ def is_flash_attn_available():
"flash_attention_4": "kernels-community/flash-attn4",
}

FLASH_ATTN_KERNEL_VERSIONS = {
"kernels-community/flash-attn2": 3,
"kernels-community/flash-attn3": 1,
"kernels-community/vllm-flash-attn3": 1,
"kernels-community/aiter-flash-attn": 1,
"kernels-community/flash-attn4": 0,
"kernels-community/metal-flash-sdpa": 1,
}

# Meta information on each mainline FA compatibility:
# 1. The import structure and availability
Expand Down
Loading
Loading