# vLLM на нескольких GPU: tensor, pipeline и data parallel

Источник: https://modelium.tech/zhurnal/vllm-neskolko-gpu/

Для одной модели, которая не помещается на одном GPU, vLLM предлагает tensor parallelism: на машине с двумя совместимыми картами начните с `--tensor-parallel-size 2`. Pipeline parallelism делит слои, а data parallelism создаёт отдельные реплики для потока запросов — это разные задачи. Проверьте реальный ответ API, журнал и загрузку обеих карт; две карты сами по себе не гарантируют ускорения или достаточной памяти.

**Проверено по документации 24 сентября 2026 года.** Ниже — воспроизводимый сценарий для владельца двух поддерживаемых GPU на Linux, а не отчёт о запуске Modelium. Версию runtime и версию скачанных весов запишите для собственного прогона. Запрос `vllm multi gpu` подтверждён подсказками Google, но частотность не измерена.

## Когда нужны два GPU, а когда достаточно одного?

Если модель с нужным контекстом и нагрузкой уже работает на одной карте, документация vLLM рекомендует не усложнять развёртывание распределённым выводом [s1](#src-s1). Второй GPU не удваивает автоматически скорость: tensor parallelism обменивается данными между картами, а реальный выигрыш зависит от модели, соединения и профиля запросов. Мы здесь не приводим ни одной измеренной скорости.

Если **одна копия модели** не помещается на одну карту, но помещается в суммарную рабочую конфигурацию одного сервера, начните с tensor parallelism (`TP`): для двух карт укажите `--tensor-parallel-size 2` [s7](#src-s7). Если у модели неудобное разбиение или нет быстрого межкарточного соединения, руководство предлагает pipeline parallelism (`PP`): слои исполняются стадиями, а не разделяются внутри слоя; для проверки альтернативы задайте `--tensor-parallel-size 1 --pipeline-parallel-size 2` [s7](#src-s7). Не обещайте, что PP всегда быстрее: это гипотеза для сравнения на своей машине. Если модель уже помещается на одном GPU и нужно обслуживать больше **независимых запросов**, data parallelism (`DP`) поднимает отдельные реплики: `--data-parallel-size 2` на двух GPU — другой путь, не способ вместить одну модель на две карты [s5](#src-s5).

        

          
        
        
Задача

      
    
        
Первая конфигурация на одном узле

      
    
        
Что проверить

      
    

`  </tr><tr>
    <td>
    <p>Одна модель не помещается на одном GPU</p>
  </td>
<td>
    <p><code>--tensor-parallel-size 2</code></p>
  </td>
<td>
    <p>API-ответ, оба процесса и память каждой карты <a href="#src-s7" rel="noopener noreferrer">s7</a></p>
  </td>

  </tr><tr>
    <td>
    <p>TP не подходит из-за деления или соединения</p>
  </td>
<td>
    <p><code>--tensor-parallel-size 1 --pipeline-parallel-size 2</code></p>
  </td>
<td>
    <p>Те же тесты и измерение на своей нагрузке <a href="#src-s7" rel="noopener noreferrer">s7</a></p>
  </td>

  </tr><tr>
    <td>
    <p>Две независимые реплики одной небольшой модели</p>
  </td>
<td>
    <p><code>--data-parallel-size 2</code></p>
  </td>
<td>
    <p>Обе реплики, маршрутизацию и пропускную способность <a href="#src-s5" rel="noopener noreferrer">s5</a></p>
  </td>

  </tr></tbody>
    </table>
  <p>Для нескольких <strong>узлов</strong> официальный пример комбинирует TP по числу карт в узле и PP по числу узлов, но требует согласованной среды, сетевой настройки и закрытого внутреннего сегмента; это не рецепт «просто подключить второй компьютер» <a href="#src-s7" rel="noopener noreferrer">s7</a>. В этой статье основной маршрут — <strong>два GPU в одной Linux-машине</strong>.</p><h2>Что подготовить для пробного запуска?</h2><p>Проверьте поддержку своего GPU и соответствие драйвера/CUDA именно выбранному пакету: документация GPU-установки перечисляет платформы отдельно и не обещает, что Linux-команда для NVIDIA подходит AMD, Intel или Mac. Нативный Windows-путь не поддерживается; WSL — отдельный сценарий с проверкой совместимости <a href="#src-s2" rel="noopener noreferrer">s2</a>. Для примера ниже предполагаются Linux, два видимых NVIDIA GPU, установленный <code>uv</code>, доступ к Hugging Face и свободное место для весов. На рабочем узле не ставьте пакет в системный Python; если драйвер/пакет не согласованы, остановитесь до скачивания модели.</p><p>Тестовый кандидат — официальный <code>Qwen/Qwen2.5-7B-Instruct</code>: карточка автора описывает instruction-вариант с меткой Apache-2.0 и рекомендует vLLM для развёртывания; текст лицензии конкретного репозитория сохранён отдельно, а условия других весов могут отличаться <a href="#src-s6" rel="noopener noreferrer">s6</a>. В его закреплённом <code>config.json</code> — 28 attention heads, четыре KV heads и <code>max_position_embeddings: 32768</code>; заявленный в карточке более длинный контекст требует отдельной настройки, которую мы здесь <strong>не включаем</strong> <a href="#src-s8" rel="noopener noreferrer">s8</a><a href="#src-s6" rel="noopener noreferrer">s6</a>. Это <strong>не</strong> заявление, что модель требует двух карт или имеет определённый минимум VRAM. Она нужна как один фиксированный кандидат для проверки параллелизма. Перед запуском оцените <a href="/zhurnal/videokarta-dlya-llm/" rel="noopener noreferrer">память под веса и контекст</a>; даже на двух GPU можно получить OOM из-за KV-кэша, графов и нагрузки <a href="#src-s4" rel="noopener noreferrer">s4</a>.</p><p>Идентификатор карточки в источниках закреплён SHA <code>a09a35458c702b33eeacc393d103063234e8bc28</code>, но команда <code>vllm serve Qwen/Qwen2.5-7B-Instruct</code> <strong>без явного snapshot-пути не закрепляет скачиваемые файлы</strong> <a href="#src-s6" rel="noopener noreferrer">s6</a>. Для повторяемого теста заранее получите snapshot нужной ревизии проверенным HF-клиентом и укажите локальный путь к нему; не публикуйте HF-токены или содержимое кэша. Сохраните версии runtime, драйвера, CUDA и ревизию фактически загруженных весов.</p><h2>Как поднять сервер на двух GPU?</h2><p>На подготовленной Linux-машине создайте отдельное окружение, установите vLLM и проверьте видимость обеих карт. Установку CUDA-колёс и её платформенные ограничения сверьте с <a href="/zhurnal/vllm/" rel="noopener noreferrer">официальной инструкцией vLLM</a> и актуальной документацией производителя <a href="#src-s2" rel="noopener noreferrer">s2</a>. Пример фиксирует опубликованную версию <code>0.18.0</code> для согласования с версионированным руководством параллелизма <a href="#src-s1" rel="noopener noreferrer">s1</a>:</p><p>nvidia-smi --query-gpu=index,name,memory.total --format=csv<br />uv venv .venv --python 3.12<br />uv pip install --python .venv/bin/python 'vllm==0.18.0'<br />CUDA_VISIBLE_DEVICES=0,1 .venv/bin/vllm serve Qwen/Qwen2.5-7B-Instruct \<br />  --tensor-parallel-size 2 \<br />  --max-model-len 2048 \<br />  --host 127.0.0.1 --port 8000<br /></p><p>Форма <code>vllm serve ... --tensor-parallel-size</code> есть в официальном руководстве <a href="#src-s1" rel="noopener noreferrer">s1</a><a href="#src-s7" rel="noopener noreferrer">s7</a>. Ограничение <code>--max-model-len 2048</code> здесь — <strong>редакционный выбор для первого короткого запроса</strong>, а не дефолт модели или обещание, что памяти хватит: документация отдельно описывает уменьшение длины контекста и batch-size как способы сократить расход <a href="#src-s4" rel="noopener noreferrer">s4</a>. <code>CUDA_VISIBLE_DEVICES=0,1</code> выбирает две карты в процессе; проверьте реальные ID и доступность в <code>nvidia-smi</code> до запуска. <code>--host 127.0.0.1</code> намеренно оставляет тестовый API внутри машины, а не выставляет его в сеть. Первая загрузка может обращаться к HF; закрытый контур проверяют отдельно после локальной загрузки весов.</p><p>Не меняйте сразу TP, размер контекста и модель: иначе ошибка или улучшение скорости не имеют понятной причины. Если подготовленный snapshot лежит на диске, подставьте его путь вместо имени HF-репозитория; это помогает воспроизвести точную ревизию при последующем сравнении. Версия документации и версия бинарного пакета должны совпасть по смыслу опций, но для своей системы проверьте доступные флаги через <code>.venv/bin/vllm serve --help</code>, прежде чем автоматизировать развёртывание.</p><h2>Как убедиться, что участвуют обе карты?</h2><p>Из другого терминала отправьте короткий Chat Completions-запрос к локальному серверу. Для этого endpoint модель должна иметь chat template — у выбранной instruction-модели он предусмотрен в карточке/репозитории; у произвольного базового чекпойнта наличие шаблона проверяют отдельно <a href="#src-s3" rel="noopener noreferrer">s3</a><a href="#src-s6" rel="noopener noreferrer">s6</a>.</p><p>curl -sS -i http://127.0.0.1:8000/v1/chat/completions \<br />  -H 'Content-Type: application/json' \<br />  -d '{"model":"Qwen/Qwen2.5-7B-Instruct","messages":[{"role":"user","content":"Ответь одним предложением: что такое tensor parallelism?"}],"max_tokens":80}'<br />nvidia-smi --query-compute-apps=gpu_uuid,pid,used_gpu_memory --format=csv<br /></p><p>Сохраните фактический HTTP-статус, непустой <code>choices[0].message.content</code>, имя модели, журнал старта и процессную память <strong>обеих</strong> карт. Если имя модели в API отличается от запроса, сначала посмотрите <code>/v1/models</code> и используйте возвращённый <code>id</code>; это не повод менять checkpoint молча <a href="#src-s3" rel="noopener noreferrer">s3</a>. Два процесса с аллокацией на двух картах и успешный ответ — проверка участия обеих карт в одном тесте; это <strong>не</strong> доказательство линейного ускорения, устойчивости под нагрузкой или правильности ответа в вашей предметной области. Документация советует также читать строки <code>GPU KV cache size</code> и <code>Maximum concurrency</code>: это оценка доступной ёмкости/параллелизма при данном контексте, а не опубликованный минимум VRAM <a href="#src-s7" rel="noopener noreferrer">s7</a>.</p><p>Для сравнения с однокарточным вариантом сохраните одинаковые ревизию модели, runtime, параметры запроса и длину контекста; измерьте latency и throughput на разрешённых тестовых запросах, пока ничего иного не изменено. Если одна карта не помещает модель, сравнение с TP=1 на той же конфигурации невозможно — не подменяйте его меньшей моделью без явной оговорки.</p><h2>Что делать при ошибке и как откатиться?</h2><ul><li><strong>Сервер не стартует или виден один GPU.</strong> Сверьте <code>CUDA_VISIBLE_DEVICES</code>, вывод <code>nvidia-smi</code>, драйвер и совместимость платформы с выбранным колесом; не переносите рецепт NVIDIA на AMD/Windows без их документации <a href="#src-s2" rel="noopener noreferrer">s2</a>.</li><li><strong>Ошибки деления голов или неправильной раскладки.</strong> На примере Qwen конфигурация указывает 28 Q-heads и четыре KV-heads; это совместимо с делением на две группы, но не является гарантией, что любой backend, квант или иная модель заведётся с TP=2 <a href="#src-s8" rel="noopener noreferrer">s8</a>. Если деление не поддерживается или соединение медленное, попробуйте отдельный PP-тест на тех же двух картах, без заявления о превосходстве скорости <a href="#src-s7" rel="noopener noreferrer">s7</a>.</li><li><strong>OOM или недостаточно места для KV-кэша.</strong> Уменьшите <code>--max-model-len</code>, нагрузку/<code>--max-num-seqs</code> или выберите другой конкретный checkpoint; сверяйте фактическую память обеих карт. Размер файла весов нельзя называть минимальным VRAM <a href="#src-s4" rel="noopener noreferrer">s4</a>.</li><li><strong>API молчит при видимых процессах.</strong> Проверьте журнал запуска, HTTP-статус, адрес <code>127.0.0.1:8000</code>, <code>/v1/models</code> и имя модели в теле запроса. Наличие процессов не означает готовность Chat Completions <a href="#src-s3" rel="noopener noreferrer">s3</a>.</li><li><strong>Сбой при распределении между узлами.</strong> Не выставляйте внутренние Ray/NCCL-порты в публичную сеть: документация предупреждает о нешифрованном межузловом трафике и необходимости приватного сегмента; диагностику NCCL выполняйте на закрытом стенде <a href="#src-s7" rel="noopener noreferrer">s7</a>.</li></ul><p>Для остановки нажмите Ctrl+C в терминале сервера; затем проверьте отсутствие занятых GPU-процессов. Удалять <code>.venv</code> можно только в каталоге собственного эксперимента, а общий HF-кэш не удаляйте без проверки других пользователей. Тестовую конфигурацию не переносите в production без проверки доступа к API, нагрузки, памяти, логов и восстановления после отказа.</p><p><strong>Следующий шаг:</strong> зафиксируйте реальный ответ API и память каждой карты, затем <a href="/zhurnal/videokarta-dlya-llm/" rel="noopener noreferrer">оцените запас под рабочую модель и контекст</a>. Если нужна альтернативная серверная реализация, откройте <a href="/zhurnal/sglang/" rel="noopener noreferrer">SGLang</a> и сравнивайте только при одинаковой задаче, ревизии весов и железе.</p>
`

## Источники

1. [vLLM 0.18.0 — Parallelism and Scaling](https://docs.vllm.ai/en/v0.18.0/serving/parallelism_scaling/) — получено 2026-09-24
2. [vLLM — GPU Installation](https://docs.vllm.ai/en/latest/getting_started/installation/gpu/) — получено 2026-09-24
3. [vLLM — Online Serving](https://docs.vllm.ai/en/latest/serving/online_serving/) — получено 2026-09-24
4. [vLLM — Conserving Memory](https://docs.vllm.ai/en/latest/configuration/conserving_memory/) — получено 2026-09-24
5. [vLLM — Data Parallel Deployment](https://docs.vllm.ai/en/latest/serving/data_parallel_deployment/) — получено 2026-09-24
6. [Qwen/Qwen2.5-7B-Instruct — карточка закреплённой ревизии](https://huggingface.co/Qwen/Qwen2.5-7B-Instruct/resolve/a09a35458c702b33eeacc393d103063234e8bc28/README.md) — получено 2026-09-24
7. [vLLM — Parallelism and Scaling, закреплённый Git commit](https://raw.githubusercontent.com/vllm-project/vllm/8b84e15066b07cf0064a0ff05f153cc85cb42817/docs/serving/parallelism_scaling.md) — получено 2026-09-24
8. [Qwen/Qwen2.5-7B-Instruct — config.json закреплённой ревизии](https://huggingface.co/Qwen/Qwen2.5-7B-Instruct/resolve/a09a35458c702b33eeacc393d103063234e8bc28/config.json) — получено 2026-09-24
