DGX Spark и его клоны поставляются с DGX OS (фактически, Ubuntu 24.04 с кучей дополнительных пакетов от Nvidia). Причем, драйвера используются довольно старые, версии 580, cuda toolkit тоже чуток устарел, 12-ой версии. Кроме того, стоит куча невразумительных пакетов с телеметрией (типа, для работы с Nvidia Sync), обвешано все какими-то левыми скриптами и странными настройками.

Не то, чтобы это создавало прямо уж совсем серьезные проблемы, но сам факт наличия какого-то непонятного bloatware меня, как бывшего системного администратора - довольно сильно расстраивал. На форуме Nvidia кто-то уже написал, что ставил чистую Ubuntu 26.04 без серьезных трудностей, так что я решил сделать так же. Попутно захотелось перейти на ZFS ради возможности точно устанавливать размер файлового кэша и компрессии.

Разумеется, сначала сделал полный бэкап на внешний nvme. Потом поставил Ubuntu 26.04 Desktop ARM, и оно даже успешно заработало, успешно установил необходимые пакеты и скомпилировал llama.cpp. Но появилась странная проблема с повышенным энергопотреблением - GX10 начал жрать из розетки во всех режимах на примерно 15 ватт больше. В idle - 41 ватт вместо 26, во время работы LLM - 195 вместо 180. Вроде бы немного, но для спарков и его клонов, с их системой охлаждения, работающей на пределе - это довольно критично.

Чатгпт раскопал пост, где кто-то сетовал на похожую проблему с портами ConnectX-7 (и, как потом оказалось, это действительно была та самая проблема), но его предложения по деактивации этих портов и выгрузке драйверов никак не помогли.

Попытка установки пакетов, типа nvidia-system-core из репозитория для DGX OS не помогли, только засорили диск частью того самого bloatware, от которого хотелось избавиться. Сначала я решил, что дело в новом ядре (26.04 идет с ядром 7.0, вместо 6.17 в DGX OS), и, чтобы убедиться - попытался поставить Ubuntu 24.04. Десктопная версия просто не смогла установиться, система падала во время инсталляции. Серверный 24.04 поставился успешно (но без ZFS, не умеет его инсталлятор этого), однако даже с ядром 6.17 проблема осталась. Пришлось экспериментировать с установкой пакетов от DGX OS, в надежде исправить. В итоге, Ubuntu 24.04 превратилась в тот самый DGX OS (после установки метапакета nvidia-system-station), но нашелся и фикс, в виде пакета dgx-spark-mlnx-hotplug, который устанавливает баш-скрипт и правила для udev, которые исправляют проблему с повышенным энергопотреблением.

После повторной инсталляции 26.04 и ручной установки этого пакета - проблема с потреблением решилась. Самые последние драйвера (610) и CUDA toolkit 13.3 установились уже без проблем, а llama.cpp заработала, по крайней мере, не хуже чем раньше (по результатам тестов llama-benchy). Однако, обнаружилось, что зажимание размера дискового кэша для ZFS не помогло vllm, который не мог работать после того завершения работы какого-нибудь жадного потребителя GPU (сам же vllm с другой моделью или llama.cpp). По прежнему приходилось освобождать кэш вручную ("sync; echo 3 | sudo tee /proc/sys/vm/drop_caches"). Ну, по крайней мере, llama.cpp работает и без этого, плюс ZFS, который ужал на примерно 11 процентов содержимое моделей (zstd-5 компрессия и дедупликация).

Вот мой рецепт по установке 26.04 на клоны спарка:

Сначала ставим Ubuntu 26.04 Desktop ARM, во время установки - ставим галочки на драйвера и third-party софт, если хочется ZFS, то на моменте конфигурирования файловых систем - выбираем advanced options, и включаем ZFS без шифрования (сильные духом - могут и шифрование включить, но тогда придется вводить пароль на каждой загрузке). После установки и перезагрузки - логинимся в терминал и включаем sshd:

sudo -i

apt install openssh-server

systemctl start ssh.service

Затем логинимся через ssh и конфигурируем остальное:

sudo -i

wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2604/sbsa/cuda-keyring_1.1-1_all.deb

dpkg -i cuda-keyring_1.1-1_all.deb

apt update

apt full-upgrade

apt install linux-nvidia-hwe-24.04-edge

apt autoremove

apt install cuda-toolkit-13-3 cuda-13-3 libnccl2 libnccl-dev libssl-dev curl cmake autoconf flex bison libtool git automake ccache

echo ‘export PATH=/usr/local/cuda/bin{PATH:+:{PATH}}’ >> ~/.bashrc

echo ‘export LD_LIBRARY_PATH=/usr/local/cuda/lib64{LD_LIBRARY_PATH:+:{LD_LIBRARY_PATH}}’ >> ~/.bashrc

apt install nvtop nvidia-container-toolkit

apt install nvidia-open cuda

apt install python3-pip python3-wheel python3-dev libpython3-dev zlib1g-dev python3-venv python3-setuptools-whl python3-setuptools python3-pip-whl

apt install docker.io docker-buildx docker-compose-v2

echo ‘options zfs zfs_arc_max=2147483648’>> /etc/modprobe.d/zfs.conf

echo ‘options zfs zfs_arc_min=1073741824’>> /etc/modprobe.d/zfs.conf

wget https://repo.download.nvidia.com/baseos/ubuntu/noble/arm64/pool/dgx/d/dgx-spark-mlnx-hotplug/dgx-spark-mlnx-hotplug_26.01-1_all.deb

dpkg -i dgx-spark-mlnx-hotplug_26.01-1_all.deb

update-initramfs -u

После этого перезагружаемся и все, система готова для клонирования репозитория llama.cpp и vllm докера от eugr - https://github.com/eugr/spark-vllm-docker

Можно еще сделать trim для ssd (теоретически, он делается раз в месяц автоматом, если spark работает круглосуточно):

zpool trim bpool

zpool trim rpool

Комментарии (3)


  1. jetnet
    19.06.2026 13:30

    Сходил в строительный магазин, купил дрель, пересобрал её дома, смазал как следует…

    Всем пока!


    1. jetnet
      19.06.2026 13:30

      Мне тоже пришлось допиливать:

      OOM костыли

      What is now installed

      I installed a vLLM-specific guard:

        /etc/systemd/system/vllm-oom-guard.service
        /usr/local/sbin/vllm-oom-guard.sh
      

      It watches:

      • MemAvailable

      • swap free

      • memory PSI pressure

      • kernel journal lines like:

        • NV_ERR_NO_MEMORY

        • oom-kill

        • Killed process

        • NVRM: Xid

      On trigger, it runs:

        docker rm -f qwen36-vllm
        tmux kill-session -t qwen36eval
        pkill -KILL -f 'run-gemma4-vllm.sh|run-qwen36-vllm.sh|VLLM::|vllm...'
      

      It already caught the later 160k Google Gemma failure:

        kernel-event NVRM ... NV_ERR_NO_MEMORY
        KILL reason=kernel-event
      

      So that part is now working.

      About auto-reboot

      I also set this as last-resort recovery:

        kernel.hung_task_timeout_secs = 120
        kernel.hung_task_panic = 1
        kernel.panic = 20
      

      Meaning:

        if a kernel task is stuck >120s,
        panic,
        then reboot after 20s
      

      That is not for normal OOM. It is for the case you just hit manually: system wedged so badly that only the power button fixed it.

      Тесты:


      1. jetnet
        19.06.2026 13:30

        У меня была задача запустить 2 “лучшие” плотные модели с FP8 квантом, вот что добился:

        Dual FP8

        Memory/startup breakdown:

          Gemma 31B FP8-block
          port: 8012
          container: dual-gemma-fp8
        
          max_model_len: 150000
          gpu_memory_utilization: 0.44
          model weights loaded: 31.70 GiB
          available KV cache: 17.93 GiB
          GPU KV cache size: 290,948 tokens
          max concurrency @150k: 1.94x
          actual cap: max_num_seqs=1
          GPU process memory: ~50.1 GiB
        
          Qwen3.6 27B FP8
          port: 8011
          container: dual-qwen-fp8
        
          max_model_len: 150000
          gpu_memory_utilization: 0.325
          model weights loaded: 28.51 GiB
          available KV cache: 4.98 GiB
          GPU KV cache size: 152,941 tokens
          max concurrency @150k: 1.02x
          actual cap: max_num_seqs=1
          GPU process memory: ~34.4 GiB
        

        Current host/container memory:

          dual-gemma-fp8 docker RAM: ~5.37 GiB / 68 GiB
          dual-qwen-fp8  docker RAM: ~7.13 GiB / 50 GiB
          host RAM used: ~100 GiB
          host RAM available: ~20 GiB
        

        Important distinction:

        • vLLM “max concurrency” means KV capacity for full 150k-token requests.

        • max_num_seqs=1 means each server is currently limited to 1 active request.

        • Together, that gives 2 total parallel requests: one Qwen + one Gemma.

        • Qwen is the tight one: 1.02x, so it cannot safely do 2 full-context requests at 150k.

        Context length:

          Currently both are served with max_model_len=150000.
        
        • Gemma config:

        export PATH="$HOME/.local/bin:$PATH"; model-shelf resolve RedHatAI/gemma-4-31B-it-FP8-block --format safetensors && docker run --rm \
          --name dual-gemma-fp8 \
          --init \
          --gpus all \
          --ipc=host \
          --shm-size=32g \
          --memory 68g \
          --memory-swap 68g \
          --oom-score-adj 900 \
          -p 0.0.0.0:8012:8000 \
          -v $HOME/.cache/model-shelf/models:/models:ro \
          vllm/vllm-openai:nightly-aarch64 \
          /models/safetensors/RedHatAI/gemma-4-31B-it-FP8-block \
          --served-model-name RedHatAI/gemma-4-31B-it-FP8-block \
          --host 0.0.0.0 \
          --port 8000 \
          --tensor-parallel-size 1 \
          --dtype bfloat16 \
          --max-model-len 150000 \
          --gpu-memory-utilization 0.44 \
          --max-num-seqs 1 \
          --max-num-batched-tokens 8192 \
          --kv-cache-dtype fp8 \
          --async-scheduling \
          --enable-prefix-caching \
          --enable-chunked-prefill \
          --load-format fastsafetensors \
          --enable-auto-tool-choice \
          --reasoning-parser gemma4 \
          --tool-call-parser gemma4 \
          --chat-template /vllm-workspace/examples/tool_chat_template_gemma4.jinja \
          --limit-mm-per-prompt '{"image": 4, "audio": 1}'
        
        • Qwen config:

        export PATH="$HOME/.local/bin:$PATH"; model-shelf resolve Qwen/Qwen3.6-27B-FP8 --format safetensors && docker run --rm \
          --name dual-qwen-fp8 \
          --init \
          --gpus all \
          --ipc=host \
          --shm-size=32g \
          --memory 50g \
          --memory-swap 50g \
          --oom-score-adj 900 \
          -p 0.0.0.0:8011:8000 \
          -v $HOME/.cache/model-shelf/models:/models:ro \
          vllm/vllm-openai:nightly-aarch64 \
          /models/safetensors/Qwen/Qwen3.6-27B-FP8 \
          --served-model-name Qwen/Qwen3.6-27B-FP8 \
          --host 0.0.0.0 \
          --port 8000 \
          --tensor-parallel-size 1 \
          --dtype bfloat16 \
          --max-model-len 150000 \
          --gpu-memory-utilization 0.325 \
          --max-num-seqs 1 \
          --max-num-batched-tokens 8192 \
          --kv-cache-dtype fp8 \
          --async-scheduling \
          --enable-prefix-caching \
          --enable-chunked-prefill \
          --load-format fastsafetensors \
          --attention-backend flashinfer \
          --enable-auto-tool-choice \
          --tool-call-parser qwen3_coder \
          --reasoning-parser qwen3 \
          --default-chat-template-kwargs '{"enable_thinking": false}'