Dev48
ЯЗЫК
  • О нас
  • Услуги
  • Индустрии
  • Технологии
  • Статьи
  • Контакты
Забронировать звонок
    Главная/Статьи/Kak ispolzovat nvidia warp i mjwarp dlya uskoreniya rabochih protsessov simulyat
Dev48

© 2026 · All rights reserved.

Как использовать NVIDIA Warp и MjWarp для ускорения рабочих процессов симуляции и обучения робототехники

Источник: Hugging Face

Как использовать NVIDIA Warp и MjWarp для ускорения рабочих процессов симуляции и обучения робототехники

Источник: Hugging Face

Запись в блоге NVIDIA на Hugging Face

25 сентября 2026 г.

Классический MuJoCo обеспечивает быструю симуляцию роботов на базе CPU для разработки, тестирования и управления роботами, а также позволяет распараллеливать выборку по ядрам CPU. Но по мере роста объемов задач обучения возникает вопрос не о том, насколько быстро может работать один мир, а о том, сколько миров может работать одновременно. Ускорение на GPU позволяет обрабатывать эти миры большими пакетами, удерживая данные симуляции и обучения непосредственно на устройстве.

MuJoCo Warp (MJWarp), созданный на базе NVIDIA Warp, переносит совместимые модели MuJoCo в режим масштабирования на GPU. В этой статье мы перенесем манипулятор-подражатель SO-101 из привычного рабочего процесса MuJoCo в среду, содержащую до 2048 параллельных окружений MJWarp, а также рассмотрим технологии и этапы проверки, которые делают этот переход возможным.

Рисунок 1. Как MJWarp связывает Python с симуляцией на GPU. MuJoCo загружает и компилирует модель MJCF; MJWarp реализует физику в NVIDIA Warp, которая компилирует ядра CUDA для продвижения состояний симуляции на GPU NVIDIA.

Это вторая статья в нашей серии «Состояние симуляции для физического искусственного интеллекта». В первой статье описывался ландшафт симуляции роботов. Здесь мы подготавливаем и масштабируем среду симуляции; мы не обучаем политику. В последующих публикациях, посвященных Newton и Isaac Lab, будут рассмотрены следующие уровни интеграции.

Подводим итоги

Краткий путь к решению:

Начните с одного полезного ядра Warp

NVIDIA Warp — это фреймворк на Python для написания высокопроизводительных ядер с ускорением на GPU. Warp позволяет разработчикам создавать статически типизированные ядра на Python и компилирует их для выполнения на CPU или CUDA. Первый запуск создает и кэширует нативный модуль; последующие запуски используют его повторно. Язык ядер представляет собой ориентированное на производительность подмножество Python, в то время как обычный Python отвечает за конфигурацию, выделение памяти и оркестрацию запускa.

Это небольшое ориентированное на робототехнику ядро обновляет положения точек под действием гравитации. Один логический поток обрабатывает одну точку, поэтому один и тот же код масштабируется от двух точек до миллионов без внедрения терминологии GPU в поток управления.

Три ценностных предложения Warp:

Три свойства делают этот инструмент полезным в робототехнике:

  • Явное параллельное выполнение. wp.tid() определяет точку, контакт, тело или мир, принадлежащие текущему логическому потоку.
  • Явные массивы устройства. Массив располагается на выбранном устройстве. Вызов .numpy() для массива CUDA синхронизирует и копирует его в память CPU; это не путь без копирования (zero-copy). Для конвейера PyTorch или JAX, работающего на устройстве, используйте вместо этого адаптеры фреймворка Warp или совместное использование, совместимое с DLPack.
  • Композитные запускы ядер. Программа может запускать последовательность специализированных ядер и захватывать поддерживаемую работу CUDA в граф, чтобы снизить накладные расходы на повторяющиеся диспетчеризации. Захват графа воспроизводит запускы с существующими буферами; он не объединяет произвольные ядра.

Дифференцируемость и детерминизм.

Стоит знать о еще двух возможностях Warp, хотя ни одна из них не используется в рабочем процессе с SO-101 в этой статье. Ядра Warp дифференцируемы: wp.Tape записывает запускы ядер в прямом направлении, сделанные в своем контексте, и воспроизводит их сопряжения в обратном порядке при вызове backward(). Именно поэтому команды создают дифференцируемую геометрию, вычислительную гидродинамику (CFD) и пользовательскую физику в Warp, включая рабочие процессы CAE для симуляции и оптимизации дизайна. Warp также поддерживает детерминированное выполнение, появившееся в Warp 1.15: атомарные операции GPU по умолчанию зависят от планировщика, поэтому повторяющиеся запускы одного и того же ядра могут немного отличаться, а опциональные детерминированные режимы жертвуют частью производительности ради воспроизводимого порядка в симуляции, валидации и регрессионных тестах. Это возможности Warp, а не гарантии дифференцируемости или детерминизма для всего развертывания MJWarp. Подробности см. в документации Warp по дифференцируемости и детерминированному выполнению.

Попробуйте Warp: pip install warp-lang (≥ 1.15 для детерминизма на GPU), затем python -m warp.examples.browse или учебные ноутбуки.

Что такое MuJoCo Warp (MJWarp)?

Симулятор робота многократно вычисляет то, что происходит дальше: учитывая текущие положения суставов, скорости, управляющие воздействия и контакты, он продвигает сцену на один малый шаг по времени. В этой статье под миром понимается одна независимая копия этой сцены и ее состояния. Один мир может содержать манипулятор SO-101, тянущийся к кубу; другой может содержать тот же манипулятор, начинающий движение из немного другой позы.

MuJoCo и MJWarp могут запускать одну и ту же совместимую задачу и робота, но они организуют работу по-разному. MuJoCo естественным образом подходит для разработки и проверки одного или нескольких миров на CPU. MJWarp — это реализация физического конвейера MuJoCo на базе NVIDIA Warp, которая размещает модель и пакет независимых состояний на графических процессорах NVIDIA; один вызов mjw.step продвигает весь пакет вперед.

Ценность MJWarp заключается не обязательно в более быстром шаге для одного мира. Она заключается в возможности продвигать сотни или тысячи миров одновременно, предоставляя GPU достаточно параллельной работы для повышения совокупной пропускной способности — общего количества шагов мира, выполненных за секунду. Это благоприятствует обучению с подкреплением и крупномасштабной выборке, где сбор опыта важнее минимизации задержки одного окружения.

В этом блоге рассматривается следующее:

  • проверка одного мира MuJoCo,
  • перенос его в MJWarp, формирование пакета,
  • проверка и корректное измерение.

Тонкая настройка решателя, представление якобиана и специализированные темы мульти-GPU или детерминизма не требуются для этой миграции и могут быть рассмотрены отдельно.

Тогда разница сформулирована точно:

  • Задержка — это время по настенным часам для одного шага симуляции.
  • Совокупная пропускная способность — это общее количество шагов мира, выполненных за измеренную секунду реального времени.

Базовое использование: структуры, размеры пакетов и минимальный шаг

  • Переход на уровне основного API невелик:

Используйте mjw.make_data(), когда требуется состояние по умолчанию / новое состояние. Используйте mjw.put_data(), когда точное инициализированное состояние MuJoCo должно пересечь границу миграции.

Выделение пакетных ресурсов требует определения следующих параметров (см. раздел «Размеры пакетов»):

Тонкая настройка производительности

1. Захват графа CUDA: mjw.step — это множество запусков ядер; захватите один раз, воспроизводите часто:

2. Задавайте размеры nconmax / naconmax / njmax точно: память и объем работы масштабируются вместе с ними. Выполняйте настройку с помощью mjwarp-testspeed: --measure_alloc и следите за переполнениями в mjwarp-viewer.

Дополнительные соображения по настройке. После определения размеров буферов контактов и ограничений протестируйте пределы итераций решателя без изменения поведения задачи. Настройки мешей и CCD могут увеличить использование памяти; nccdmax / naccdmax могут уменьшить выделение памяти под буфер CCD, если это позволяют измеренные количества контактов. Компактный решатель MJWarp использует ньютоновский решатель ограничений MuJoCo и переход в спящий режим, а не отдельный фреймворк физического движка Newton. Конфигурация компактного решателя и мульти-GPU выходит за рамки этого руководства; обратитесь к документации по настройке производительности MJWarp.

Для обучения политик на физике MJWarp:

  • Isaac Lab через Newton
  • mjlab (manager API непосредственно поверх MJWarp + PyTorch)
  • MuJoCo Playground через MJX (impl='warp')

Установка / тестирование: pip install mujoco-warp · mjwarp-viewer path/to/scene.xml · Учебник Colab

Рабочий процесс миграции сцены MuJoCo в MjWarp

  • Создание базового уровня MuJoCo на CPU

Создание базового уровня MuJoCo на CPU

Сцена. Здесь пока нет ничего специфичного для MJWarp: рука SO-101, стол и два кубика для установки друг на друга, описанные в обычном формате MJCF.

Рисунок 2. Сцена захвата и размещения SO-101, отрендеренная из CPU-симуляции MuJoCo. Задача состоит в том, чтобы захватить красный кубик размером 44 мм и установить его на синий кубик; те же робот и сцена используются для валидации MJWarp.

Для коробочки MJCF значения size представляют собой полуразмеры: size=”0.022 …” определяет кубик с ребрами 44 мм. Задача использует этот размер для определения порогов успешности. Основание руки находится в начале координат, зона досягаемости простирается вдоль +X, а кубики расположены вдоль Y.

В сопутствующем репозитории этот файл генерируется, а не пишется вручную: resolve_pick_place_scene() копирует руку из Menagerie в .generated/, заполняет координаты стола и кубиков на основе профиля робота и записывает scene_pick_place.xml. В пошаговом руководстве используется профиль SO-101; опциональный вариант reBot описан ниже.

Загрузка. Компиляция и выполнение шагов происходят как в обычном MuJoCo:

Держите эту структуру в уме: вычислять управляющие воздействия один кадр за раз, выполнять шаги физики sim_substeps раз. В Шаге 2 изменяется только внутренний цикл, что и делает миграцию простой для проверки.

Согласуйте частоту симуляции и управления. При 50 управляющих кадрах в секунду и 10 физических подшагах на кадр используйте физический временной шаг 0,002 секунды. Установите его перед запуском на CPU и перед выгрузкой модели с помощью mjw.put_model, чтобы оба бэкенда продвигались на одинаковое симулированное время:

Без этой строки каждое последующее измерение наследует несоответствие: сравнения на идентичность (паритет), показатели пропускной способности, указываемые как «симулированные секунды», и любая обученная политика, чья частота действий больше не совпадает с развертыванием.

Проверьте, успешно ли сложены кубики. Для 44-мм кубиков успех определяется двумя измеряемыми условиями: горизонтальной погрешностью центра xy_err ≤ 0,015 м (измеряется между центрами кубиков) и вертикальным зазором 0,035 м ≤ dz ≤ 0,055 м между центрами кубиков (одна грань кубика с допуском на усадку). Оценивайте оба условия после того, как кубики улягутся; сам по себе успешный выход из процесса не доказывает успешность выполнения задачи.

Запустите задачу на CPU из сопутствующего репозитория. Блокирующий фактор для публикации: подтвердите доступный URL репозиторий, а также зафиксированные версии зависимостей и ассетов перед публикацией этих инструкций; заменитель URL репозитория ниже не является исполняемым.

Запуск завершается выводом двух приведенных выше чисел (stack check: xy_err=… dz=…), что является утверждением (ассертом), с которым сравнивается остальная часть статьи. so101_pick_place.py рядом с ним — это та же программа, но шаги физики оставлены в качестве упражнений.

Рука взята напрямую из MuJoCo Menagerie и зафиксирована на проверенном коммите, так как ассеты Menagerie меняются, поэтому рассматривайте сцену как шаблон. Опциональный вариант reBot. Сопутствующий код также предоставляет --robot rebot с отдельным профилем для компоновки сцены, захвата и пределов вместимости (nconmax=256, njmax=500). В этом руководстве используется SO-101. Проверьте ассет reBot и задачу отдельно, прежде чем сообщать их результаты.

  • Валидация одномирового паритета MJWarp

Валидация одномирового паритета MJWarp

Сначала запустите один мир на GPU, оставив хост в контуре, чтобы вы могли наблюдать за той же задачей в том же визуализаторе и сравнить те же два числа. Загрузите модель, выделите пакетное состояние, инициализируйте его из инициализированного состояния хоста и выполните один прямой проход перед выполнением шага:

Каждый массив устройства имеет ведущее измерение мира, поэтому к состоянию хоста обращаются как mjd.qpos[None, :], размерность (1, nq) вместо (nq,). Масштабирование до тысяч миров позже меняет только это ведущее измерение, а не вызовы. mjw.put_model() также служит проверкой совместимости: он вызывает ошибку, если модель использует неподдерживаемые функции, вместо того чтобы молча отбрасывать их.

Явная инициализация трех полей является прозрачным вариантом и дает понять, что именно передается на устройство; вместо этого mjw.put_data(mjm, mjd, nworld=…) переносит всю инициализированную структуру за один вызов.

Цикл кадров тогда представляет собой цикл Шага 1 с перенаправлением его внутреннего шага на GPU и зеркальным отображением обратно:

Вызовы .numpy() синхронизируют и копируют данные на хост на каждом подшаге, поэтому это путь валидации задачи, а не бенчмарк пропускной способности. Он сохраняет обратную кинематику, визуализацию и проверки задач на хосте. После копирования qpos и qvel вызовите mujoco.mj_forward(mjm, mjd) для обновления производных величин хоста, таких как mjd.xpos, перед их использованием для управления, визуализации или проверки стека. Чтение этих полей после цикла не обновляет их автоматически. Шаг 4 удаляет эти копии на хосте для каждого шага из пути измерения пропускной способности.

  • Определение емкости контактов и ограничений

Определение емкости контактов и ограничений

MJWarp выделяет буферы контактов и ограничений перед выполнением шагов. Превышение этой емкости делает соответствующий прогон недействительным для верификации или бенчмаркинга, даже если выполнение продолжается с предупреждением переполнения, а не с исключением. Увеличьте соответствующий предел и перезапустите задачу. Большие буферы используют больше памяти GPU, поэтому проверьте емкость для всей задачи перед окончательным сужением выделения памяти.

Установите лимиты контактов и ограничений для симулируемых робота и задачи. Профиль SO-101 использует nconmax=128 и njmax=300 в качестве начальной емкости. Убедитесь, что эти лимиты достаточны во время наиболее насыщенной контактами части задачи:

Рассчитывайте их под наиболее насыщенный контактами момент задачи: для захвата и размещения — момент, когда оба губных захвата и стол касаются кубика, а не когда рука зависает в свободном пространстве. Переполнение сообщается, а не вызывает ошибку: при значении Option.warn_overflow по умолчанию MJWarp выводит в терминал вашей программы или визуализатора бюджет, который нужно увеличить («narrowphase overflow - please increase nconmax to …»), и помечает затронутые миры в Data.overflow для чтения после шага. Только mjw.put_data вызывает ошибку напрямую, так как она может сравнить бюджеты с уже имеющимся у нее состоянием MuJoCo. mjwarp-testspeed --measure_alloc сообщает о контактах и ограничениях, которые сцена фактически потребила, и прерывает симуляцию с указанием идентификаторов проблемных миров, как только в каком-либо мире происходит переполнение. Относитесь к таким отчетам как к сбоям: увеличьте лимит и перезапустите симуляцию, прежде чем доверять траектории или бенчмарку, а затем снова уменьшайте лимит при каждом изменении модели, геометрии столкновений или задачи.

  • Масштабирование до 2048 миров

Масштабирование до 2048 миров

Как только одномировый паритет пройдет успешно, перераспределите память под целевой размер и реплицируйте инициализированное состояние по всему батчу. По сравнению с Шагом 2 меняются две вещи: nworld и тот факт, что через шину PCIe на каждый шаг ничего не передается.

np.tile задает для каждого мира одинаковое начальное состояние, что является правильной отправной точкой для измерения пропускной способности; рандомизация для каждого мира вместо этого записывала бы разные строки d.qpos на устройстве.

CUDA Graphs повторно используют модель и буферы данных, захваченные здесь. Обновляйте d.ctrl на месте между перезапусками и захватывайте новый граф после замены буферов, изменения nworld или пересборки модели. Захват графа требует наличия CUDA.

Рисунок 3. Масштабирование задачи SO-101 с одного процессорного мира до 2048 независимых состояний GPU с использованием той же совместимой модели. Один шаг MJWarp продвигает весь батч. Эта концептуальная иллюстрация подчеркивает совокупную пропускную способность, измеряемую как шаги мира в секунду реального времени.

  • Проверьте, затем измерьте

Проверьте, затем измерьте

Запуски GPU выполняются асинхронно, поэтому наивный таймер измеряет скорость постановки задач в очередь Python, а не скорость их выполнения на GPU. Сначала выполните прогрев — при первых запусках происходят компиляция ядра и выделение памяти — а затем синхронизируйте выполнение непосредственно перед и после измеряемой области:

Указывайте как совокупное количество шагов мира в секунду, так и миллисекунды на батчевый шаг вместе с размером батча. Используйте измеренную кривую, чтобы определить, где добавление миров увеличивает пропускную способность, а где ограничения памяти или вычислений снижают этот эффект. Результаты зависят от сцены, настроек симуляции и аппаратного обеспечения; сравнение задержки для одного мира не определяет пропускную способность батча.

Чтобы увидеть эту кривую на вашем собственном оборудовании, скрипт scaling_study.py перебирает размер батча и выводит мс/шаг наряду с пропускной способностью и ускорением:

Начало работы

Warp (слой ядер) pip install warp-lang → python -m warp.examples.browse → docs · GitHub

MJWarp (GPU MuJoCo) pip install mujoco-warp → mjwarp-viewer benchmarks/humanoid/humanoid.xml → docs · GitHub · Colab tutorial

Контекст SO-101 Курс SO-101 sim-to-real · Пути обучения физическому ИИ

Обучение поверх MJWarp mjlab · MuJoCo Playground · Isaac Lab + Newton (будущие публикации)

Что дальше

В этой статье рассматривались основы Warp → MJWarp: ядра GPU, батчевый шаг и сцена SO-101 с использованием mjw.step.

Затем мы перенесем ту же среду MJCF в Newton, используя MuJoCo Warp в качестве решателя твердых тел (newton.solvers.SolverMuJoCo). Newton будет управлять моделью, состоянием, управлениями и контактами, в то время как MJWarp работает «под капотом».

Вы также увидите, что добавляет Newton: многоформатные ассеты, заменяемые решатели, помощники сенсоров/ИК и путь Isaac Lab.

Руководство по миграции продолжается с той же задачей SO-101 и ее опциональным профилем reBot, объясняя изменения, требуемые Newton, и отдельную интеграцию с Isaac Lab.

Если вы создаете что-то с помощью Warp или MJWarp, откройте issue в связанных репозиториях или найдите нас в Discord NVIDIA Omniverse.

Ссылки

  • Блог 1: *Состояние симуляции для физического ИИ: обзор* — Публикация 1 из этой серии.
  • NVIDIA Warp — GitHub · Документация · Релиз v1.15.0 (детерминизм GPU) · Руководство по детерминированному выполнению
  • MuJoCo Warp — GitHub · Официальная документация MJWarp
  • Создание ускоренного дифференцируемого кода вычислительной физики для ИИ с помощью NVIDIA Warp
  • Представляем плитное программирование (Tile-Based Programming) в Warp 1.5.0
  • mjlab · arXiv:2601.22074
  • MuJoCo Playground
  • Курс NVIDIA SO-101 sim-to-real
  • Следующая публикация Newton: MJWarp в качестве SolverMuJoCo и перенос этой среды
← Все статьи