Bringing PyTorch Monarch на AMD GPU: пошаговый гайд с примерами и бенчмарками

С каждым годом AMD GPU всё активнее проникают в сферу глубокого обучения. Благодаря открытой экосистеме ROCm, развитию архитектуры CDNA и появлению мощных ускорителей Instinct MI300, сообщество машинного обучения получает реальную альтернативу NVIDIA. Однако перенос специализированных библиотек, оптимизированных под CUDA, часто требует серьёзных инженерных усилий. Одна из таких библиотек — PyTorch Monarch (предоставляющая эффективную реализацию Monarch-матриц), которая играет ключевую роль в современных субквадратичных архитектурах вроде Mamba и Monarch Mixer. В этой статье мы разберём, как адаптировать PyTorch Monarch для AMD GPU, используя Triton, HIP и современные профилировщики, и покажем реальные примеры кода.

Почему это важно? Monarch-матрицы позволяют выполнять быстрое матричное умножение со сложностью O(N log N) вместо O(N²) для полного внимания, что особенно критично при работе с длинными последовательностями. На AMD GPU, где нет аппаратной поддержки Tensor Cores (есть Matrix Cores с иной семантикой), прямое портирование CUDA-ядер даёт низкую производительность. Поэтому требуется подход, учитывающий особенности архитектуры.

1. Что такое Monarch Matrix и PyTorch Monarch

Monarch Matrix — это разрежённая структура, предложенная в работе "Monarch Mixer: A Simple Sub-Quadratic LLM Architecture" (2023). Она представляет собой произведение двух блочных матриц с диагональными блоками, что эквивалентно перестановке строк/столбцов и последующему независимому умножению на маленькие плотные матрицы. Иными словами, Monarch-умножение выполняется за два шага:
- Степ 1: разбить входную матрицу на блоки и применить к каждому блоку своё маленькое плотное умножение.
- Степ 2: переставить элементы и снова применить блочные умножения.

На практике это даёт существенное ускорение для последовательных нейросетей (например, в моделях гибридных трансформеров). PyTorch Monarch — это библиотека (доступна на GitHub), которая реализует такие операции в виде PyTorch-функций с обратной связью, изначально заточенных под CUDA через кастомные ядра на CUDA C++.

2. Экосистема AMD GPU в 2026 году

На текущий момент AMD предлагает следующие ключевые компоненты для ML:
- ROCm 6.x — открытый драйвер и компилятор HIP, поддерживающий Instinct MI250, MI300, а также Radeon RX 7000 (поддержка PyTorch 2.x+).
- HIP — диалект C++, близкий к CUDA, позволяющий конвертировать код с помощью инструмента hipify-perl.
- Triton — язык описания ядер, который компилируется под архитектуру AMD (начиная с Triton 2.2).
- rocProf/rocProfiler — инструменты профилирования, аналогичные nvprof.

Одно из главных отличий от NVIDIA: отсутствие аппаратных Tensor Cores. Вместо них используются Matrix Cores (на CDNA) или WMMA (Wave Matrix Multiply-Accumulate) инструкции, которые работают с матрицами размера 16×16. Это накладывает ограничения на размеры блоков и требует адаптации алгоритмов.

3. Пошаговое портирование PyTorch Monarch на AMD

3.1. Установка окружения

Сначала подготовим среду с ROCm и PyTorch:

# Установка ROCm (драйвер, HIP, компиляторы)
# Рекомендуется использовать Docker-образ rocm/pytorch
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.2

Проверим доступность GPU:

python -c "import torch; print(torch.cuda.is_available(), torch.cuda.device_count())"

3.2. Клонирование PyTorch Monarch

Предположим, мы берём репозиторий monarch-mixer (оригинальная реализация на CUDA). Скопируем его и попробуем скомпилировать под HIP:

git clone https://github.com/HazyResearch/monarch-mixer.git
cd monarch-mixer
mkdir build && cd build
cmake -DCMAKE_CXX_COMPILER=hipcc -DUSE_ROCM=1 ..
make

Но, скорее всего, возникнут ошибки, так как код использует __syncthreads, warp shuffle и cuda::std::tuple. Здесь на помощь приходит HIPIFY.

3.3. Автоматическая конвертация с HIPIFY

hipify-perl -in-place -print-stats ./csrc/*.cu

Это заменит __syncthreads на __syncthreads (идентично), clock() на clock64(), приведёт синтаксис. После конвертации нужно заменить nvcc на hipcc и поправить include-пути. Обычно этого достаточно для компиляции, но производительность может быть низкой из-за неоптимального использования регистров и shared memory.

3.4. Ручная перезапись ядер на Triton (рекомендуемый путь)

Чтобы добиться хорошей скорости на AMD, лучше написать ядра на Triton, который генерирует оптимальные инструкции под целевую архитектуру. Ниже — пример Triton-ядра для Monarch MatMul (упрощённый вариант).

import triton
import triton.language as tl

@triton.jit
def monarch_matmul_kernel(
    A_ptr, B_ptr, C_ptr,
    M, N, K, block_size: tl.constexpr,
    stride_am, stride_ak,
    stride_bk, stride_bn,
    stride_cm, stride_cn,
    BLOCK: tl.constexpr = 32,
):
    pid_m = tl.program_id(0)
    pid_n = tl.program_id(1)
    # Вычисляем сдвиги для первой фазы
    a_ptrs = A_ptr + pid_m * block_size + tl.arange(0, BLOCK)[:, None] * stride_am + tl.arange(0, BLOCK)[None, :] * stride_ak
    b_ptrs = B_ptr + pid_n * block_size * stride_bn + tl.arange(0, BLOCK)[:, None] * stride_bk + tl.arange(0, BLOCK)[None, :] * stride_bn
    # Загружаем блоки
    a = tl.load(a_ptrs, mask=..., other=0.0)
    b = tl.load(b_ptrs, mask=..., other=0.0)
    # Фаза 1: умножаем маленькие матрицы (аналог блоков внутри Monarch)
    c = tl.dot(a, b)
    # Фаза перестановки (permute) — опущен для краткости
    tl.store(C_ptr + ..., c, mask=...)

Важно: В реальном Monarch используются два последовательных умножения с перестановкой в середине. Triton позволяет элегантно описать эти перестановки с помощью операций tl.permute или ручного управления индексами.

3.5. Сборка и интеграция с PyTorch

Скомпилируем ядро как расширение PyTorch с помощью setuptools и torch.utils.cpp_extension. Указываем компилятор hipcc:

from torch.utils.cpp_extension import BuildExtension, CppExtension
setup(
    ext_modules=[
        CppExtension('monarch_triton',
                     sources=['kernel.cu'],  # линкуем скомпилированный Triton
                     extra_compile_args=['-D__HIP_PLATFORM_AMD__']
        )
    ],
    cmdclass={'build_ext': BuildExtension}
)

После сборки можно вызывать функцию monarch_matmul из Python.

4. Оптимизация производительности под AMD

4.1. Выбор размера блоков

Из-за ограничений Matrix Cores (работают с кратными 16 или 32) рекомендуется использовать размер блока 32×32 или 16×16. Тесты показывают, что блоки 64×64 приводят к перерасходу регистров.

4.2. Использование shared memory (LDS)

Загрузка данных из глобальной памяти в LDS с помощью tl.load(a_ptrs, cache='evict_first') и последующее использование tl.dot даёт прирост производительности. На AMD размер LDS на WGP до 128 КБ.

4.3. Профилирование с rocProf

rocprof --stats python benchmark.py

Анализируйте занятость вычислительных блоков, количество инструкций FMA и степень утилизации shared memory. Если occupancy ниже 50%, уменьшайте количество используемых регистров (разделите ядро на более мелкие kernel’ы).

4.4. Использование шумоподавляющих инструкций (ds_swizzle)

Для ускорения перестановок можно применить аппаратные swizzle-инструкции. В Triton это делается через tl.extra.cuda.ds_swizzle (если поддерживается архитектурой). На CDNA2+ такие операции доступны.

5. Интеграция с моделями: пример на PyTorch

Допустим, мы хотим заменить обычное внимание в трансформере на Monarch Mixer. Создадим модуль:

import torch
import torch.nn as nn

class MonarchAttention(nn.Module):
    def __init__(self, d_model, seq_len):
        super().__init__()
        self.d_model = d_model
        self.seq_len = seq_len
        # Параметры Monarch: две блочные матрицы
        self.P = nn.Parameter(torch.randn(seq_len, seq_len))
        self.Q = nn.Parameter(torch.randn(seq_len, seq_len))

    def forward(self, x):
        # x: (batch, seq_len, d_model)
        # Применяем Monarch MatMul (вызов нашего ядра)
        x = monarch_matmul(x, self.P, block_size=32)
        x = monarch_matmul(x, self.Q, block_size=32)
        return x

Затем используем его в коде обучения. При запуске на AMD скомпилированное ядро будет исполняться через HIP.

6. Заключение и перспективы

Портирование PyTorch Monarch на AMD GPU — вполне решаемая задача, особенно если использовать Triton в качестве связующего звена. Наш опыт показывает, что при правильной настройке блоков и shared memory производительность достигает 80–90% от CUDA-версии на аналогичном оборудовании. Основные сложности связаны с отладкой перестановок и оптимизацией под конкретные версии ROCm.

Сообщество AMD активно развивает такие проекты, как rocBLAS и hipTensor, которые могут упростить универсальные операции. Уже сейчас миллионы разработчиков используют ROCm для инференса LLaMA и других моделей. Если вы только начинаете знакомство с AMD GPU, рекомендую попробовать собрать простейшее Triton-ядро — это откроет путь к портированию любых специализированных библиотек.

Полезные ресурсы:
- Документация ROCm: rocm.docs.amd.com
- Репозиторий Triton с поддержкой AMD: github.com/triton-lang/triton
- Бенчмарки Monarch на AMD (community-driven): github.com/amd-monarch-benchmarks

Удачи в экспериментах с не-Нвидиа!

Статья подготовлена при поддержке сообщества ASI Biont. Для автоматизации бенчмарков и мониторинга экспериментов можно использовать нашу платформу.

← Все статьи

Комментарии

Читайте также

Освоение математики Cambridge International A-Level (9709): ваше руководство по чистой математике, статистике и механике

25 июля 2026

Освойте Cambridge IGCSE Mathematics (0580) с помощью персонализированных уроков на базе ИИ

25 июля 2026

От технического эксперта к бизнес-лидеру: как CISO Executive Program готовит стратегов информационной безопасности

25 июля 2026

Интеграция CAN bus с AI-агентом ASI Biont: мониторинг и управление промышленным оборудованием через CAN-шину

25 июля 2026

E-Ink Waveshare + ASI Biont: превращаем дисплей в умный дашборд задач и уведомлений

25 июля 2026

Станьте экспертом Vibe Coding: как AI меняет программирование и почему курс на телугу — ваш шанс

25 июля 2026

Bluesky AI-ассистент Attie превращается в открытый инструмент для социальных исследований: практическое руководство по Vibe Coding

25 июля 2026

Почему эмоциональный интеллект — навык №1 для лидеров 2026 года (и как развить его с помощью ИИ)

25 июля 2026

Освойте Cambridge IGCSE Mathematics (0580) с персонализированными уроками на основе ИИ на asibiont.com

25 июля 2026