Новинка NVIDIA B300 · серверы 288 ГБ HBM3e — от 4 019 $/мес. за GPU

Посмотреть B300

Документация · Приложения

JupyterLab на GPU-сервере

Запустите JupyterLab на GPU-сервере, который вы контролируете: PyTorch с поддержкой GPU в отдельном окружении, служба systemd на localhost с паролем и доступ через SSH-туннель.

Обновлено 11 мин чтения

Установите JupyterLab и PyTorch на GPU-сервер

Чтобы запустить JupyterLab на GPU-сервере, установите его вместе со сборкой PyTorch для CUDA или ROCm в виртуальное окружение Python, настройте службу systemd, которая запускает JupyterLab с паролем на 127.0.0.1:8888, и откройте его в браузере через SSH-туннель. Jupyter-ноутбуки при этом выполняются на GPU сервера, и ни один порт не доступен из интернета. Если при заказе вы выбрали JupyterLab на шаге «ПО», он уже установлен; это руководство описывает, как установить и запустить его самостоятельно.

Выполняйте команды от имени root в Ubuntu 22.04 или 24.04, кроме шагов, где вы переключаетесь на alice — обычного пользователя из руководства Ваш первый час на новом GPU-сервере. Никогда не запускайте JupyterLab от имени root: его ноутбуки и терминал получают права пользователя, от имени которого он работает. Сначала установите драйвер GPU (Драйверы NVIDIA и CUDA; на AMD MI355X — ROCm на MI355X). На NVIDIA в заголовке вывода nvidia-smi должно быть CUDA Version 13.0 или выше: wheel-пакеты PyTorch содержат собственные библиотеки CUDA, а программы для CUDA 13.x работают на драйверах серии 580 и новее (заметки о выпуске CUDA).

adduser alice                      # пропустите, если alice уже существует
usermod -aG render,video alice     # только для AMD MI355X
su - alice

# от имени alice: uv, затем Python 3.13 в отдельном окружении
curl -LsSf https://astral.sh/uv/install.sh | sh
~/.local/bin/uv venv --python 3.13 --seed --managed-python ~/jupyter-env
source ~/jupyter-env/bin/activate

pip install torch torchvision --index-url https://download.pytorch.org/whl/cu132      # NVIDIA
# pip install torch torchvision --index-url https://download.pytorch.org/whl/rocm7.14 # AMD MI355X
pip install jupyterlab
python -c "import torch; print(torch.cuda.is_available(), torch.cuda.device_count())"

Команды для PyTorch — те, что приводит pytorch.org для версии 2.14.1 (проверено 20 октября 2026 г.). На любом GPU NVIDIA используйте сборку для CUDA 13.2, а не вариант CUDA 12.6, который селектор на сайте тоже предлагает: поддержка Blackwell появилась в PyTorch 2.7 вместе со сборками для CUDA 12.8. Команда pip install jupyterlab из руководства по установке JupyterLab заодно устанавливает ipykernel, поэтому ядро Python 3 по умолчанию работает в этом окружении и с этим PyTorch. Подходящие GPU — на страницах об исследованиях и о дообучении.

Запустите JupyterLab как службу systemd

Служба запускается при загрузке системы и перезапускается после сбоя. Сначала задайте пароль — всё ещё от имени alice. Jupyter Server хранит только хеш пароля — в файле ~/.jupyter/jupyter_server_config.json:

jupyter server password      # спросит пароль дважды и запишет хеш
exit                         # вернуться к root

От имени root разместите ноутбуки и кэш Hugging Face на NVMe-диске для данных в /data (Хранилище и данные), затем создайте юнит:

mkdir -p /data/notebooks /data/hf
chown alice:alice /data/notebooks /data/hf
tee /etc/systemd/system/jupyterlab.service >/dev/null <<'EOF'
[Unit]
Description=JupyterLab
After=network.target

[Service]
User=alice
WorkingDirectory=/data/notebooks
Environment=HF_HOME=/data/hf
ExecStart=/home/alice/jupyter-env/bin/jupyter-lab --no-browser --ip=127.0.0.1 --port=8888 --port-retries=0 --notebook-dir=/data/notebooks --MappingKernelManager.cull_idle_timeout=7200
NoNewPrivileges=yes
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now jupyterlab
ss -tln | grep 8888            # 127.0.0.1:8888 и больше ничего
journalctl -u jupyterlab -f    # журнал; Ctrl-C прекращает отслеживание
  • --ip=127.0.0.1 оставляет сервер на loopback-адресе. С --port-retries=0 он завершается с ошибкой, если порт 8888 занят, а не переходит на один из 50 следующих портов, так что ваш туннель никогда не ведёт на неверный порт.
  • cull_idle_timeout=7200 завершает ядра, простаивающие два часа без подключённого браузера, и тем самым освобождает память GPU, занятую забытыми ноутбуками; ядра, которые выполняют код, не завершаются (параметры Jupyter Server).
  • NoNewPrivileges=yes не даёт ничему, что запущено из JupyterLab, повысить привилегии через setuid-программы вроде sudo: административные задачи выполняйте в своей SSH-сессии.

Если пароль не задан, Jupyter Server при каждом запуске создаёт новый случайный токен и записывает в журнал URL для входа с этим токеном; от имени root этот URL также выводит команда su - alice -c '~/jupyter-env/bin/jupyter server list'.

Откройте JupyterLab через SSH-туннель

На своём компьютере пробросьте локальный порт на loopback-адрес удалённого сервера, затем откройте http://localhost:8888 и войдите со своим паролем:

ssh -N -L 8888:127.0.0.1:8888 gpu1

# порт 8888 на вашем компьютере уже занят, например локальным Jupyter
ssh -N -L 8889:127.0.0.1:8888 gpu1      # затем откройте http://localhost:8889

gpu1 — это запись host из раздела Доступ по SSH; если добавить в неё строку LocalForward, туннель будет открываться при каждом подключении. В Windows та же команда работает в PowerShell. Если закрыть браузер или туннель, ваши ядра продолжат работать.

Никогда не запускайте JupyterLab с --ip=0.0.0.0 и никогда не открывайте порт 8888 в файрволе: любой, кто получит доступ, сможет выполнять код и открыть терминал от имени alice. Для команды используйте JupyterHub (см. ниже). В Docker публикуйте порт как -p 127.0.0.1:8888:8888, потому что правила портов Docker обходят ufw (см. Контейнеры).

Проверьте в Jupyter-ноутбуке, что PyTorch видит GPU

Откройте ноутбук с ядром Python 3 (ipykernel) и выполните:

import torch
print(torch.__version__, "CUDA:", torch.version.cuda, "HIP:", torch.version.hip)
print("GPUs:", torch.cuda.device_count(), torch.cuda.is_available())
for i in range(torch.cuda.device_count()):
    free, total = torch.cuda.mem_get_info(i)
    print(i, torch.cuda.get_device_name(i), f"{free / 2**30:.0f} of {total / 2**30:.0f} GiB free")
print(torch.cuda.get_arch_list())   # MI355X: в списке должен быть gfx950
x = torch.randn(8192, 8192, device="cuda")
print((x @ x).sum().item())         # умножение матриц на GPU 0

Ожидаемый вывод: версия, оканчивающаяся на +cu132 или +rocm7.14, True и по одной строке на каждый GPU с его названием и памятью. Сборка для ROCm использует те же интерфейсы torch.cuda, поэтому этот код без изменений работает и на MI355X (семантика HIP). Если is_available() возвращает False, выполните в терминале nvidia-smi или amd-smi list и вернитесь к руководству по драйверу.

Пакеты из ноутбука устанавливайте командой %pip install <package>: она запускает pip в текущем ядре (магические команды IPython), поэтому пакеты попадают в ~/jupyter-env.

Выбирайте GPU для каждого Jupyter-ноутбука и следите за памятью GPU

Ядро видит все GPU, если его не ограничить. Задайте CUDA_VISIBLE_DEVICES в первой ячейке, до import torch; чтобы изменить значение, перезапустите ядро. Или зарегистрируйте отдельное ядро для каждого GPU — тогда переменная задаётся ещё до запуска ядра:

import os
os.environ["CUDA_VISIBLE_DEVICES"] = "1"   # это ядро видит только GPU 1, под именем cuda:0
import torch
# от имени alice: добавляет в список ядро Python (GPU 1)
source ~/jupyter-env/bin/activate
python -m ipykernel install --user --name gpu1 --display-name "Python (GPU 1)" --env CUDA_VISIBLE_DEVICES 1

Номера соответствуют порядку в выводе nvidia-smi, а видимые GPU нумеруются заново с 0 (переменные окружения CUDA). На MI355X используйте HIP_VISIBLE_DEVICES (ROCm на MI355X). Та же команда, запущенная из другого окружения, добавляет в качестве ядра это окружение (установка ядра).

Чтобы найти ядро, которое занимает память GPU, выполните в терминале:

nvidia-smi                       # в таблице процессов — каждый PID и его память GPU
amd-smi process -G               # AMD MI355X: PID, имя процесса, память
ps -o pid,etime,args -p <pid>    # ядра ноутбуков — это процессы ipykernel_launcher

В самом ноутбуке:

print(torch.cuda.memory_allocated() / 2**30, torch.cuda.memory_reserved() / 2**30)   # ГиБ в тензорах, ГиБ зарезервировано
print(torch.cuda.memory_summary())
del model                  # удалите то, что больше не нужно
torch.cuda.empty_cache()   # верните неиспользуемую память из кэша

Кэширующий аллокатор PyTorch удерживает освобождённую память для повторного использования, а nvidia-smi и amd-smi показывают её как занятую. empty_cache() освобождает эту неиспользуемую часть, но не трогает память, которую ещё занимают тензоры (управление памятью). Чтобы освободить всю память, перезапустите ядро. Если закрыть ноутбук, его ядро продолжит работать и занимать память: завершайте ядра на вкладке Running в левой боковой панели, где перечислены запущенные ядра и терминалы (документация JupyterLab).

Длительное обучение без прерываний

Ядра переживают закрытие браузера, но не остановку самого JupyterLab. Останавливаясь, Jupyter Server завершает свои ядра, а systemd убивает все процессы, оставшиеся в контрольной группе службы (KillMode). Поэтому при перезапуске службы, обновлении, перезагрузке или сбое переменные и модели в памяти теряются; файлы ноутбуков остаются в последнем сохранённом виде.

Всё, что длится часами, запускайте как скрипт вне JupyterLab и сохраняйте чекпоинты в /data. Команда jupyter nbconvert --to script превращает ноутбук в скрипт на Python; удалите из него магические команды вроде %pip, которые работают только в Jupyter (nbconvert). Затем от имени root запустите скрипт как временную (transient) службу systemd:

su - alice -c 'cd /data/notebooks && ~/jupyter-env/bin/jupyter nbconvert --to script train.ipynb'

systemd-run --unit=train --uid=alice --working-directory=/data/notebooks \
  -E CUDA_VISIBLE_DEVICES=0 -E HF_HOME=/data/hf \
  /home/alice/jupyter-env/bin/python -u train.py
journalctl -u train -f          # следить за выводом; Ctrl-C не останавливает запуск
systemctl stop train            # остановить запуск
systemctl reset-failed train    # после неудачного запуска освобождает имя

Такой запуск переживает завершение SSH-сессии и перезапуски JupyterLab, но не перезагрузку сервера, а -u отключает буферизацию вывода Python, поэтому журнал всегда актуален. Подойдёт и tmux (Доступ по SSH). Чтобы продолжить после прерывания, возобновите обучение с последнего чекпоинта, как в руководстве Дообучение LLM с LoRA и QLoRA.

Альтернатива: JupyterLab в Docker

Сначала установите Docker и NVIDIA Container Toolkit (Контейнеры). Официальные Jupyter Docker Stacks публикуют варианты pytorch-notebook для CUDA; тегам cuda13- нужен драйвер серии 580 или новее. Перед запуском остановите службу, созданную выше, или опубликуйте другой порт хоста, например 127.0.0.1:8890:8888:

mkdir -p /data/work && chown 1000 /data/work    # UID 1000 — это jovyan, пользователь в образе
docker run -d --name jupyter --gpus all --restart unless-stopped \
  -p 127.0.0.1:8888:8888 \
  -v /data/work:/home/jovyan/work \
  quay.io/jupyter/pytorch-notebook:cuda13-2026-10-19
docker logs jupyter 2>&1 | grep token            # URL для входа

Тег с датой фиксирует все версии; cuda13-latest следует за новыми сборками. При замене контейнера сохраняется только /home/jovyan/work. Образ PyTorch из NVIDIA NGC тоже содержит JupyterLab (4.6.3 в выпуске 26.09): запускайте его с теми же параметрами --gpus all и -p 127.0.0.1:8888:8888 и командой jupyter lab --ip=0.0.0.0 --no-browser --allow-root. Порт, опубликованный на 127.0.0.1, доступен только с самого хоста (публикация портов в Docker), поэтому 0.0.0.0 внутри контейнера не открывает доступ извне. GPU-варианты Docker Stacks собраны для CUDA: на MI355X используйте установку без Docker, описанную выше.

Несколько пользователей: JupyterHub, а не общий JupyterLab

Один сервер JupyterLab — это один пользователь. Каждый, у кого есть пароль, работает от имени alice, с теми же файлами, правами и GPU, а документация Jupyter Server предупреждает, что команды нескольких человек на одном сервере могут конфликтовать и перезаписывать друг друга (запуск публичного сервера).

Чтобы у каждого была своя учётная запись, используйте JupyterHub — многопользовательский хаб, который запускает для каждого человека отдельный однопользовательский сервер, управляет этими серверами и проксирует к ним запросы. По умолчанию пользователи входят под своими локальными учётными записями Unix. The Littlest JupyterHub собирает его в готовый дистрибутив для групп до 100 пользователей на одном сервере. Следуйте его документации: в ней сказано, что в каждом развёртывании нужно включить HTTPS, а для этого требуется доменное имя, направленное на сервер. Пользователи одного сервера всё равно делят его GPU: договоритесь, кто какими GPU пользуется, или выделите каждому свой сервер.

Сделайте резервную копию Jupyter-ноутбуков до окончания срока

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

su - alice -c '~/jupyter-env/bin/pip freeze > /data/notebooks/requirements.txt'

# с вашего компьютера
rsync -avhP gpu1:/data/notebooks/ ./notebooks/

На следующем сервере окружение воссоздаёт команда pip install -r requirements.txt --extra-index-url https://download.pytorch.org/whl/cu132 (на MI355X — rocm7.14). Большие датасеты и чекпоинты отправляйте в объектное хранилище через rclone, как показано в разделе Хранилище и данные.

Нужна помощь с этим руководством?

Расскажите нам о своём GPU, командах, которые вы выполнили, и результате, который получили, через форму обратной связи.

Личный кабинет

Войти в CryptGPU

Ваши заказы, счета и серверы в одном месте.

Новичок в CryptGPU?

Аккаунты создаются при оформлении заказа: выберите сервер и программное обеспечение, затем создайте аккаунт на шаге Аккаунт первого заказа.

Запустить сервер