System Info
transformers version: 5.15.0
- Platform: macOS-26.3.1-arm64-arm-64bit-Mach-O
- Python version: 3.13.5
- PyTorch version (GPU?): 2.13.0 (False)
- Accelerate version: 1.14.0
- MPS available: True
- Using distributed or parallel set-up in script?: No
(also reproduced on transformers 5.14.1 and Python 3.11)
Who can help?
@Cyrilvallez
Information
Tasks
Reproduction
import torch
from transformers import AutoModelForCausalLM
AutoModelForCausalLM.from_pretrained(
"trl-internal-testing/tiny-Qwen3ForCausalLM", # any checkpoint stored in bf16
dtype=torch.float32,
device_map="auto", # resolves to MPS; {"": "mps"} also crashes
)
# -> SIGSEGV (exit 139). faulthandler places the crash in the worker threads of
# core_model_loading._materialize_copy.
All four conditions are required:
- checkpoint stored in bf16 (a checkpoint stored in f32 loads fine, e.g.
hf-internal-testing/tiny-random-LlamaForCausalLM)
- requested
dtype=torch.float32 (forces a dtype conversion; loading as bf16 is fine)
- MPS target (
device_map="auto" or {"": "mps"}; device_map="cpu" is fine)
- async loading active (the default).
HF_DEACTIVATE_ASYNC_LOAD=1 avoids the crash.
What we ruled out (isolation attempts that do NOT reproduce):
- pure torch:
ThreadPoolExecutor workers doing t.to(torch.float32).to("mps") -> OK
- mmap-backed safetensors (
get_tensor) converted to mps in workers -> OK
- the exact
_materialize_copy pattern (get_slice, tensor[...] inside the worker, combined .to(device="mps", dtype=torch.float32)) with 1 and 8 workers -> OK
So the crash seems to be an interaction inside the full loading pipeline (workers materializing while the main thread also touches MPS), not a broken primitive.
Expected behavior
Model loads, or a clean error.
Note this combination is common in practice: TRL's GRPOTrainer(model="...") passes dtype=float32 + device_map="auto" by default, so it segfaults on macOS for most modern (bf16) checkpoints.
Possible fix: convert_and_load_state_dict_in_model already disables the thread pool for disk offload and on-the-fly quantization (each with its own reason). Adding an MPS carve-out to that same condition avoids the crash:
or any((d == "mps" or getattr(d, "type", None) == "mps") for d in device_map.values())
Happy to send that PR if the carve-out is acceptable, or to test a deeper fix.
System Info
transformersversion: 5.15.0(also reproduced on transformers 5.14.1 and Python 3.11)
Who can help?
@Cyrilvallez
Information
Tasks
Reproduction
All four conditions are required:
hf-internal-testing/tiny-random-LlamaForCausalLM)dtype=torch.float32(forces a dtype conversion; loading as bf16 is fine)device_map="auto"or{"": "mps"};device_map="cpu"is fine)HF_DEACTIVATE_ASYNC_LOAD=1avoids the crash.What we ruled out (isolation attempts that do NOT reproduce):
ThreadPoolExecutorworkers doingt.to(torch.float32).to("mps")-> OKget_tensor) converted to mps in workers -> OK_materialize_copypattern (get_slice,tensor[...]inside the worker, combined.to(device="mps", dtype=torch.float32)) with 1 and 8 workers -> OKSo the crash seems to be an interaction inside the full loading pipeline (workers materializing while the main thread also touches MPS), not a broken primitive.
Expected behavior
Model loads, or a clean error.
Note this combination is common in practice: TRL's
GRPOTrainer(model="...")passesdtype=float32+device_map="auto"by default, so it segfaults on macOS for most modern (bf16) checkpoints.Possible fix:
convert_and_load_state_dict_in_modelalready disables the thread pool for disk offload and on-the-fly quantization (each with its own reason). Adding an MPS carve-out to that same condition avoids the crash:Happy to send that PR if the carve-out is acceptable, or to test a deeper fix.