Если вы разработчик, исследователь или энтузиаст искусственного интеллекта, который работает на Mac с чипами Apple Silicon, то последние годы могли быть для вас периодом компромиссов. Да, вы могли запускать модели, но часто это требовало обходных путей, борьбы с непредсказуемым ростом потребления памяти и падениями производительности на определенных операциях. Однако ситуация кардинально меняется. Выход PyTorch 2.15 знаменует собой поворотный момент, превращающий macOS из «второго сорта» в полноценную платформу для обучения и инференса нейросетей. Команда Hugging Face, тесно сотрудничающая с разработчиками PyTorch, проделала колоссальную работу по миграции ключевых вычислений из абстрактного слоя MPSGraph на нативные Metal-ядра, что дало измеримый прирост скорости и стабильности.
В этой статье мы подробно разберем, что именно изменилось в PyTorch 2.15. Мы поговорим о долгожданной поддержке формата FP8, которая позволяет экономить память без потери качества, о том, как ускорилось декодирование больших языковых моделей (LLM), и о решении критической проблемы с переполнением памяти при работе с видео-моделями. Это не просто список изменений — это руководство к тому, как получить максимум от вашего Mac в 2026 году.
01Требования и начало работы
Прежде чем погружаться в технические детали, важно убедиться, что ваше окружение готово к новым возможностям. PyTorch 2.15 вводит более строгие системные требования, что является частью общей стратегии по оптимизации и безопасности. Теперь для работы бэкенда MPS требуется macOS 15 (Sequoia) или новее, а также Python 3.11 или новее. Это не просто бюрократическое требование: новые версии операционной системы содержат оптимизации в драйверах Metal, которые критически важны для производительности новых ядер.
Если вы попытаетесь запустить код на старой версии macOS, система теперь корректно сообщит об ошибке, а не будет молча падать или использовать медленные CPU-альтернативы. Для тех, кто хочет протестировать возможности релиза, доступна версия кандидата в релизы (release candidate). Вы можете установить её в изолированной среде, используя инструмент uv или pip:
uv pip install torch==2.15.0 --index-url https://download.pytorch.org/whl/test/cpuОбратите внимание на URL: он указывает на тестовый канал. Для стабильной работы в продакшене рекомендуется ждать официального релиза, но для экспериментов с новыми функциями, такими как FP8, эта версия уже готова.
02FP8 на Mac: Экономия памяти без компромиссов
Одной из самых ожидаемых функций в PyTorch 2.15 является поддержка формата чисел с плавающей точкой float8_e4m3fn (FP8) на бэкенде MPS. До этого момента Mac-пользователи были ограничены форматами FP16 (half precision) и BF16 (bfloat16). Хотя BF16 отлично подходит для обучения, он занимает 2 байта на значение. FP8 же занимает всего 1 байт, что позволяет вдвое сократить потребление памяти для весов моделей и промежуточных активаций.
Почему это важно? В больших языковых моделях (LLM) память часто является узким местом. Возможность использовать FP8 означает, что вы можете либо запустить более крупную модель на том же оборудовании, либо увеличить размер батча (batch size), что ускоряет инференс. PyTorch 2.15 добавляет поддержку умножения матриц с масштабированием через функцию F.scaled_mm, которая поддерживает как поэлементное, так и построчное масштабирование. Это позволяет сохранить точность вычислений, компенсируя меньшую разрядность формата.
Вот пример того, как можно квантовать тензор в FP8 и выполнить умножение:
import torch
import torch.nn.functional as F
def quantize_fp8(x):
limit = torch.finfo(torch.float8_e4m3fn).max
scale = x.abs().amax().clamp_min(1e-12) / limit
return (x / scale).to(torch.float8_e4m3fn), scale
x = torch.randn(1024, device="mps", dtype=torch.float32)
weight = torch.randn(1024, 1024, device="mps", dtype=torch.float32)
x_fp8, x_scale = quantize_fp8(x)
w_fp8, w_scale = quantize_fp8(weight)
y = F.scaled_mm(
x_fp8,
w_fp8.t(),
scale_a=x_scale,
scale_recipe_a=F.ScalingType.TensorWise,
scale_b=w_scale,
scale_recipe_b=F.ScalingType.TensorWise,
output_dtype=torch.bfloat16,
)
print(y.shape, y.dtype)Этот код демонстрирует базовый паттерн: мы находим максимальное абсолютное значение в тензоре, вычисляем масштабный коэффициент и приводим данные к типу FP8. Результат умножения возвращается в BF16, что обеспечивает баланс между точностью и скоростью. Поддержка FP8 открывает двери для работы с моделями, которые ранее были недоступны для локального запуска на Mac из-за нехватки VRAM.

03Ускорение декодирования LLM: От MoE до линейных слоев
Декодирование больших языковых моделей — это процесс генерации текста по одному токену за раз. Этот этап состоит из двух фаз: prefill (заполнение контекста) и decode (генерация каждого следующего токена). Именно фаза decode часто становится «бутылочным горлышком», так как она требует множества последовательных вызовов модели, и каждый вызов должен быть максимально быстрым.
Линейные слои и матрично-векторные умножения
В PyTorch 2.14 ядра GEMV (Matrix-Vector) для операции torch.mm уже существовали, но функция F.linear, которая повсеместно используется в слоях трансформеров, все еще проходила через медленный слой MPSGraph. В версии 2.15 эта связь устранена. Теперь входные данные формата [1, 1, hidden_size], характерные для декодирования, напрямую используют оптимизированные Metal-ядра. Это дает геометрическое среднее ускорение в 1.23 раза на 96 различных формах слоев BF16 из реальных моделей. Наибольшую выгоду получают небольшие проекционные слои, такие как гейты в моделях с архитектурой Mixture-of-Experts (MoE), где ранее большая часть пропускной способности памяти простаивала.
Модели Mixture-of-Experts (MoE)
Самым впечатляющим улучшением стало ускорение моделей MoE. Архитектура MoE позволяет модели активировать только часть параметров для каждого токена, что делает её эффективной. Однако управление разными «экспертами» требует сложной маршрутизации. В предыдущих версиях PyTorch смещения групп копировались на CPU, и цикл по группам выполнялся там, что создавало задержки.
В PyTorch 2.15 реализована нативная поддержка grouped matmul (сгруппированного умножения матриц) непосредственно в Metal. Ядра считывают смещения групп прямо на GPU, используя Metal Performance Shaders (MPS) там, где это возможно, и отдельные Metal-пути в других случаях. Для малых групп, которые являются типичными во время декодирования, созданы специализированные ядра. Результат? На чипе M3 Ultra модель Qwen3.6-35B-A3B с использованием torch.compile увеличила скорость генерации с 9.4 токенов в секунду до 61.3 токенов в секунду. Это ускорение в 6.5 раз!
Другая модель, LFM2.5-8B-A1B, показала рост с 23.6 до 123.6 токенов в секунду. Даже плотные модели (dense models) получают преимущество от более быстрых линейных слоев и оптимизированного софтмакса.


Софтмакс: 8-кратное ускорение
Еще одним узким местом при выборе следующего токена является операция softmax над всем словарем. В PyTorch 2.15 softmax и log_softmax теперь выполняются через выделенные Metal-ядра. Для больших словарей, например, размером 128 256 токенов, время выполнения FP32 softmax сократилось с 57 микросекунд до 7 микросекунд. Это ускорение в 8 раз по сравнению с версией на MPSGraph. Такое улучшение критически важно для моделей с огромными словарями, так как снижает задержку на каждый сгенерированный токен.
04Линейная алгебра: Больше вычислений на GPU
PyTorch 2.15 расширяет возможности линейной алгебры, доступные на GPU Mac. Теперь операции с комплексными числами (complex64) поддерживают факторизацию LU, решение систем линейных уравнений (LU solve) и треугольные решения (triangular solve). Это открывает возможности для научных вычислений и специализированных моделей, которые ранее требовали возврата на CPU.
Также ускорены операции с малыми матрицами. Для задач компьютерного зрения и геометрии камер, где часто встречаются батчи матриц размером до 4x4, теперь используется единое Metal-ядро, объединяющее факторизацию и решение. Это значительно быстрее, чем последовательные вызовы общих операций. Кроме того, улучшена устойчивость алгоритма SVD (сингулярного разложения) при работе с экстремально малыми или большими значениями, что повышает надежность вычислений псевдообратных матриц и решений методом наименьших квадратов.
import torch
a = torch.randn(4, 4, device="mps", dtype=torch.complex64)
a = a + 1j * torch.eye(4, device="mps", dtype=torch.complex64)
b = torch.randn(4, device="mps", dtype=torch.complex64)
lu, pivots = torch.linalg.lu_factor(a)
x = torch.linalg.lu_solve(lu, pivots, b)
print((a @ x - b).abs().max().item())05Видео и аудио: Решение проблемы с памятью
Одним из самых драматичных улучшений в PyTorch 2.15 является исправление проблемы с потреблением памяти при декодировании видео-моделей, в частности, архитектуры Wan2.2. Ранее, при декодировании видео с использованием tiled VAE (Variational Autoencoder), драйверная память могла достигать 270 ГБ, что делало невозможным запуск таких задач на большинстве Mac, даже с большим объемом RAM. Это происходило из-за неэффективного управления памятью при операциях дополнения (padding).
В новой версии операция constant padding перенесена в нативные Metal-ядра. Это изменение привело к снижению пикового потребления памяти драйвера с 270 ГБ до всего 8 ГБ. При этом общее количество вызовов padding за одно декодирование видео составляет 8 764, и каждый из них теперь обрабатывается эффективно.

Также улучшены операции reflection и replication padding, которые теперь работают быстрее и корректнее. Для аудио-моделей добавлены специализированные ядра для conv1d (одномерной свертки), что полезно для потоковой обработки звука. Операции nn.Dropout и F.dropout теперь используют объединенное ядро, а обратное распространение для интерполяции (upsampling backward) перенесено на Metal, что ускоряет обучение моделей.
06Контроль потоков и новые операции
Разработчики получили больше контроля над выполнением задач на GPU. В PyTorch 2.15 появился публичный API для работы с потоками MPS (torch.mps.Stream). Вы можете явно указывать, в каком потоке выполнять операции, и синхронизировать их. Это полезно для асинхронной обработки данных, например, когда одна часть кода готовит данные, а другая обрабатывает их на GPU.
import torch
x = torch.randn(1024, device="mps")
torch.mps.synchronize()
worker = torch.mps.Stream()
with torch.mps.stream(worker):
y = x.square()
x.record_stream(worker)
del worker
worker.synchronize()
print(y.cpu().shape)Также добавлена поддержка ряда новых операций, таких как torch.frexp, torch.logspace, torch.take, torch.heaviside и полиномы Лагерра. Исправлена корректность работы механизма внимания (attention) при.broadcasting по батчу и головам, что устраняло ошибки в некоторых сложных архитектурах.
torch.logspace пока не поддерживает целочисленные или булевы выходы с более чем одним элементом. Если ваш код зависит от этой функциональности, будьте осторожны.07Взгляд в будущее: PyTorch 2.16
Работа над следующей версией, PyTorch 2.16, уже активно ведется. Среди ключевых планов — полное перемещение механизма внимания (attention) на Metal, исключая MPSGraph. Это даст дополнительный прирост скорости, особенно для моделей с grouped-query attention (GQA). Ожидается, что задержка декодирования на M5 Pro снизится с 465 мкс до 65 мкс для определенных конфигураций.
Также продолжается миграция других операций, таких как batch normalization, MSE loss и bincount. Последняя операция демонстрирует впечатляющий результат: подсчет 4 миллионов целых чисел, попадающих в один бин, сократился с 6.8 секунд до 0.5 миллисекунды. Кроме того, размер бинарного файла libtorch_cpu.dylib уменьшится примерно на 25% благодаря оптимизации бандлированных шейдеров.
08Что это значит на практике
Для конечного пользователя, который запускает модели через библиотеки transformers, diffusers или интерфейсы вроде ComfyUI, PyTorch 2.15 означает следующее:
- Локальные LLM работают значительно быстрее. Если у вас Mac с чипом M3 Ultra или M4, вы можете генерировать текст в 5-6 раз быстрее, чем в предыдущих версиях. Это делает интерактивное использование больших моделей (например, Qwen3.6 или LFM2.5) комфортным и практически мгновенным.
- Генерация видео стала возможной. Проблема с переполнением памяти при работе с Wan2.2 решена. Теперь вы можете генерировать видео на Mac, не боясь, что система зависнет из-за потребления 270 ГБ памяти. Пиковое потребление составляет около 8 ГБ, что доступно даже на моделях с 16 ГБ унифицированной памяти.
- Качество обработки изображений исправлено. В предыдущих версиях кодировщик VAE модели Qwen-Image-2.1 на MPS мог искажать изображения. В 2.15 это исправлено, и качество восстановления (PSNR) вернулось к уровню CPU (29.95 dB против 10.06 dB ранее).
- FP8 открывает новые горизонты. Вы можете использовать модели с весами FP8, экономя память. Это особенно актуально для запуска очень больших моделей на Mac с 32-64 ГБ памяти.
Команда Hugging Face и PyTorch продолжает работу над улучшением бэкенда MPS. Следующие версии обещают еще больше операций, перенесенных с MPSGraph на нативные Metal-ядра, и лучшую интеграцию с torch.compile. Если вы сталкиваетесь с проблемами, медленной работой или отсутствующими операциями, сообщайте об этом в GitHub-репозиторий PyTorch. Сообщество активно развивается, и Mac становится все более мощной платформой для искусственного интеллекта.
Рекомендуем обновить PyTorch до версии 2.15 и протестировать новые возможности на ваших любимых моделях. Разница в производительности и стабильности будет очевидна.
Источник: Hugging Face ↗
