Zum Inhalt springen →

Installation vllm auf dem Jetson Orin 64GB Developer Kit

vLLM (Vectorized Low-Latency Machine Learning) ist eine Bibliothek, die speziell für die Beschleunigung der Inferenz entwickelt wurde. vLLM ermöglicht es, Transformer-basierte Architekturen mit minimaler Latenz und maximalem Durchsatz auszuführen, was es zu einer idealen Wahl für Echtzeitanwendungen macht.

Quelle: https://x.com/MagicAmish/status/1884424865534685323

vLLM nutzt fortschrittliche Techniken wie PagedAttention und effizientes Speichermanagement, um die Hardware-Ressourcen optimal auszulasten. Dies ist besonders wichtig, wenn man auf leistungsstarker, aber ressourcenbeschränkter Hardware wie dem NVIDIA Jetson Orin arbeitet. Der Jetson Orin ist eine hervorragende Plattform für die lokale Nutzung von KI-Modellen.

Im folgenden werde ich Schritt für Schritt durch die Installation und Konfiguration von vLLM auf dem Jetson Orin führen.

Voraussetzungen

Die vLLM Installation benötigt eine Installation von torch, torchvision und torchaudio. Die Installation der 3 Pakete habe ich unter https://www.jentsch.io/pytorch-aus-den-sourcen-mit-cuda-12-support-bauen-und-installieren/ schon mal beschrieben.

Zusätzlich wird auch das triton Paket benötig, das mit folgenden Befehlen auch aus den Sourcen installiert werden kann.

git clone https://github.com/triton-lang/triton.git
cd triton
pip install ninja cmake wheel pybind11 # build-time dependencies
pip install -e python

Die Installation dauert relativ lange, also erst mal einen Kaffee trinken…..

Installation aus den Sourcen

Ist die Installation von torch, torchvision und torchaudio erledigt, muss das vLLM Repository geklont werden.

$ git clone https://github.com/vllm-project/vllm.git
$ cd vllm

Leider kann man nun nicht einfach „pip install -e .“ ausführen und die Installation läuft ohne Probleme durch. Der Versuch mündet in folgendem Fehler:

Collecting vllm
  Using cached vllm-0.7.0.tar.gz (5.0 MB)
  Installing build dependencies ... done
  Getting requirements to build wheel ... error
  error: subprocess-exited-with-error

  × Getting requirements to build wheel did not run successfully.
  │ exit code: 1
  ╰─> [16 lines of output]
      Traceback (most recent call last):
        File "/home/michael/projects/mistralai-Mistral-Small-24B-Instruct-2501/env/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 363, in <module>
          main()
        File "/home/michael/projects/mistralai-Mistral-Small-24B-Instruct-2501/env/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 345, in main
          json_out['return_val'] = hook(**hook_input['kwargs'])
        File "/home/michael/projects/mistralai-Mistral-Small-24B-Instruct-2501/env/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 130, in get_requires_for_build_wheel
          return hook(config_settings)
        File "/usr/local/lib/python3.10/dist-packages/setuptools/build_meta.py", line 325, in get_requires_for_build_wheel
          return self._get_build_requires(config_settings, requirements=['wheel'])
        File "/usr/local/lib/python3.10/dist-packages/setuptools/build_meta.py", line 295, in _get_build_requires
          self.run_setup()
        File "/usr/local/lib/python3.10/dist-packages/setuptools/build_meta.py", line 311, in run_setup
          exec(code, locals())
        File "<string>", line 627, in <module>
        File "<string>", line 525, in get_vllm_version
      RuntimeError: Unknown runtime environment
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× Getting requirements to build wheel did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.

vLLM basiert auf PyTorch und kann auf unterschiedlichen Umgebungen unterschiedlich kompiliert oder konfiguriert werden, insbesondere auf spezialisierter Hardware wie NVIDIA Jetson-Geräten. In solchen Fällen ist es oft besser, die bereits installierte, hardwareoptimierte Version von PyTorch zu verwenden, anstatt eine neue, möglicherweise inkompatible Version zu installieren.

Das use_existing_torch.py-Skript im vLLM-Repository dient dazu, sicherzustellen, dass vLLM eine bereits installierte Version von PyTorch verwendet, anstatt eine neue Version zu installieren. Dies ist besonders nützlich in Umgebungen, in denen PyTorch bereits speziell für eine bestimmte Hardware (z. B. NVIDIA Jetson mit aarch64-Architektur) kompiliert oder optimiert wurde.

Das use_existing_torch.py-Skript überprüft, ob PyTorch bereits installiert ist, und passt die Abhängigkeiten von vLLM entsprechend an. Es verhindert, dass während der Installation von vLLM eine neue Version von PyTorch heruntergeladen und installiert wird, die möglicherweise nicht für die spezifische Hardware optimiert ist.

Die folgenden Befehle bereiten die Installation vor, indem sie die vorhandene PyTorch-Installation überprüfen und die notwendigen Build-Abhängigkeiten installieren.

  • python use_existing_torch.py 
    stellt sicher, dass die bereits installierte PyTorch-Version verwendet wird, anstatt eine neue, möglicherweise inkompatible Version zu installieren.
  • pip install -r requirements-build.txt 
    installiert alle erforderlichen Build-Abhängigkeiten, die für die Kompilierung und Installation von vllm notwendig sind.
python use_existing_torch.py
pip install -r requirements-build.txt
pip install -vvv -e . --no-build-isolation

Die Zeile pip install -vvv -e . --no-build-isolation installiert das vllm-Paket im Entwicklungsmodus (-e) direkt aus dem aktuellen Verzeichnis (.). Die Option -vvv erhöht die Ausführlichkeit der Ausgabe, sodass detaillierte Informationen während der Installation angezeigt werden. --no-build-isolation deaktiviert die Isolierung des Build-Prozesses, was bedeutet, dass bereits installierte Pakete im aktuellen Environment verwendet werden, anstatt eine isolierte Umgebung zu erstellen.

Der Entwicklungsmodus, der mit -e (oder --editable) aktiviert wird, ermöglicht es, ein Python-Paket direkt aus dem Quellcodeverzeichnis zu installieren, ohne es zu kopieren. Stattdessen wird ein symbolischer Link zum Quellcodeverzeichnis erstellt. Das bedeutet, dass Änderungen am Quellcode sofort wirksam werden, ohne dass das Paket erneut installiert werden muss. Dies ist besonders nützlich während der Entwicklung, da es das Testen und Iterieren von Code beschleunigt.

Nach der erfolgreichen Installation von vLLM auf dem Jetson Orin Developer Kit kann man vllm -h aufrufen und sollte folgende Ausgabe erhalten.

$ vllm -h
INFO 01-31 07:26:55 __init__.py:183] Automatically detected platform cuda.
usage: vllm [-h] [-v] {serve,complete,chat} ...

vLLM CLI

positional arguments:
  {serve,complete,chat}
    serve               Start the vLLM OpenAI Compatible API server
    complete            Generate text completions based on the given prompt via the running API server
    chat                Generate chat completions via the running API server

options:
  -h, --help            show this help message and exit
  -v, --version         show program's version number and exit

Nutzung

Den ersten Test mache ich mal mit dem NousResearch/Meta-Llama-3-8B-Instruct. Das Model besteht aus 4 safetensors Dateien, die in Summe ca. 16GB groß sind. Der Start eines vllm Servers auf dem Port 444455 mit dem NousResearch/Meta-Llama-3-8B-Instruct Model sieht wie folgt aus:

vllm serve NousResearch/Meta-Llama-3-8B-Instruct --dtype auto --api-key token-abc123 --port 44455
INFO 02-01 13:30:08 __init__.py:183] Automatically detected platform cuda.
INFO 02-01 13:30:09 api_server.py:838] vLLM API server version 0.7.1.dev42+g41bf5612.d20250130
INFO 02-01 13:30:09 api_server.py:839] args: Namespace(subparser='serve', model_tag='NousResearch/Meta-Llama-3-8B-Instruct', config='', host=None, port=44455, uvicorn_log_level='info', allow_credentials=False, allowed_origins=['*'], allowed_methods=['*'], allowed_headers=['*'], api_key='token-abc123', lora_modules=None, prompt_adapters=None, chat_template=None, chat_template_content_format='auto', response_role='assistant', ssl_keyfile=None, ssl_certfile=None, ssl_ca_certs=None, ssl_cert_reqs=0, root_path=None, middleware=[], return_tokens_as_token_ids=False, disable_frontend_multiprocessing=False, enable_request_id_headers=False, enable_auto_tool_choice=False, enable_reasoning=False, reasoning_parser=None, tool_call_parser=None, tool_parser_plugin='', model='NousResearch/Meta-Llama-3-8B-Instruct', task='auto', tokenizer=None, skip_tokenizer_init=False, revision=None, code_revision=None, tokenizer_revision=None, tokenizer_mode='auto', trust_remote_code=False, allowed_local_media_path=None, download_dir=None, load_format='auto', config_format=<ConfigFormat.AUTO: 'auto'>, dtype='auto', kv_cache_dtype='auto', max_model_len=None, guided_decoding_backend='xgrammar', logits_processor_pattern=None, distributed_executor_backend=None, pipeline_parallel_size=1, tensor_parallel_size=1, max_parallel_loading_workers=None, ray_workers_use_nsight=False, block_size=None, enable_prefix_caching=None, disable_sliding_window=False, use_v2_block_manager=True, num_lookahead_slots=0, seed=0, swap_space=4, cpu_offload_gb=0, gpu_memory_utilization=0.9, num_gpu_blocks_override=None, max_num_batched_tokens=None, max_num_seqs=None, max_logprobs=20, disable_log_stats=False, quantization=None, rope_scaling=None, rope_theta=None, hf_overrides=None, enforce_eager=False, max_seq_len_to_capture=8192, disable_custom_all_reduce=False, tokenizer_pool_size=0, tokenizer_pool_type='ray', tokenizer_pool_extra_config=None, limit_mm_per_prompt=None, mm_processor_kwargs=None, disable_mm_preprocessor_cache=False, enable_lora=False, enable_lora_bias=False, max_loras=1, max_lora_rank=16, lora_extra_vocab_size=256, lora_dtype='auto', long_lora_scaling_factors=None, max_cpu_loras=None, fully_sharded_loras=False, enable_prompt_adapter=False, max_prompt_adapters=1, max_prompt_adapter_token=0, device='auto', num_scheduler_steps=1, multi_step_stream_outputs=True, scheduler_delay_factor=0.0, enable_chunked_prefill=None, speculative_model=None, speculative_model_quantization=None, num_speculative_tokens=None, speculative_disable_mqa_scorer=False, speculative_draft_tensor_parallel_size=None, speculative_max_model_len=None, speculative_disable_by_batch_size=None, ngram_prompt_lookup_max=None, ngram_prompt_lookup_min=None, spec_decoding_acceptance_method='rejection_sampler', typical_acceptance_sampler_posterior_threshold=None, typical_acceptance_sampler_posterior_alpha=None, disable_logprobs_during_spec_decoding=None, model_loader_extra_config=None, ignore_patterns=[], preemption_mode=None, served_model_name=None, qlora_adapter_name_or_path=None, otlp_traces_endpoint=None, collect_detailed_traces=None, disable_async_output_proc=False, scheduling_policy='fcfs', override_neuron_config=None, override_pooler_config=None, compilation_config=None, kv_transfer_config=None, worker_cls='auto', generation_config=None, override_generation_config=None, enable_sleep_mode=False, calculate_kv_scales=False, disable_log_requests=False, max_log_len=None, disable_fastapi_docs=False, enable_prompt_tokens_details=False, dispatch_function=<function serve at 0xfffec7419240>)
INFO 02-01 13:30:09 api_server.py:204] Started engine process with PID 87566
config.json: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 654/654 [00:00<00:00, 3.85MB/s]
INFO 02-01 13:30:14 __init__.py:183] Automatically detected platform cuda.
INFO 02-01 13:30:20 config.py:526] This model supports multiple tasks: {'classify', 'generate', 'reward', 'score', 'embed'}. Defaulting to 'generate'.
tokenizer_config.json: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 51.0k/51.0k [00:00<00:00, 4.75MB/s]
tokenizer.json: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 9.09M/9.09M [00:03<00:00, 2.57MB/s]
special_tokens_map.json: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 73.0/73.0 [00:00<00:00, 469kB/s]
INFO 02-01 13:30:26 config.py:526] This model supports multiple tasks: {'score', 'embed', 'generate', 'classify', 'reward'}. Defaulting to 'generate'.
INFO 02-01 13:30:26 llm_engine.py:232] Initializing a V0 LLM engine (v0.7.1.dev42+g41bf5612.d20250130) with config: model='NousResearch/Meta-Llama-3-8B-Instruct', speculative_config=None, tokenizer='NousResearch/Meta-Llama-3-8B-Instruct', skip_tokenizer_init=False, tokenizer_mode=auto, revision=None, override_neuron_config=None, tokenizer_revision=None, trust_remote_code=False, dtype=torch.bfloat16, max_seq_len=8192, download_dir=None, load_format=auto, tensor_parallel_size=1, pipeline_parallel_size=1, disable_custom_all_reduce=False, quantization=None, enforce_eager=False, kv_cache_dtype=auto,  device_config=cuda, decoding_config=DecodingConfig(guided_decoding_backend='xgrammar'), observability_config=ObservabilityConfig(otlp_traces_endpoint=None, collect_model_forward_time=False, collect_model_execute_time=False), seed=0, served_model_name=NousResearch/Meta-Llama-3-8B-Instruct, num_scheduler_steps=1, multi_step_stream_outputs=True, enable_prefix_caching=False, chunked_prefill_enabled=False, use_async_output_proc=True, disable_mm_preprocessor_cache=False, mm_processor_kwargs=None, pooler_config=None, compilation_config={"splitting_ops":[],"compile_sizes":[],"cudagraph_capture_sizes":[256,248,240,232,224,216,208,200,192,184,176,168,160,152,144,136,128,120,112,104,96,88,80,72,64,56,48,40,32,24,16,8,4,2,1],"max_capture_size":256}, use_cached_outputs=True,
generation_config.json: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 187/187 [00:00<00:00, 1.18MB/s]
INFO 02-01 13:30:29 cuda.py:230] Using Flash Attention backend.
INFO 02-01 13:30:30 model_runner.py:1110] Starting to load model NousResearch/Meta-Llama-3-8B-Instruct...
INFO 02-01 13:30:34 weight_utils.py:251] Using model weights format ['*.safetensors']
model-00003-of-00004.safetensors:   2%|██▍                                                                                                              | 105M/4.92G [02:35<1:59:39, 670kB/s]
model-00004-of-00004.safetensors:   9%|██████████▎                                                                                                        | 105M/1.17G [02:37<26:36, 666kB/s]
model-00001-of-00004.safetensors:   2%|██▍                                                                                                              | 105M/4.98G [02:37<2:02:09, 665kB/s]
model-00002-of-00004.safetensors:   2%|██▎                                                                                                              | 105M/5.00G [02:38<2:03:10, 662kB/s]

Der Download läuft (~ 2 Stunden) und es ist mal wieder Zeit für einen Kaffee 🙂

Fazit

Die Installation von vLLM auf einem Jetson Orin 64GB Developer Kit mit aarch64-Architektur erfordert zwar viel Geduld, da viele Pakete aus den Quellen kompiliert werden müssen, aber der Aufwand lohnt sich. vLLM ist eine hochoptimierte und effiziente Bibliothek für das Inferencing von Large Language Models (LLMs), die eine erhebliche Beschleunigung und Ressourceneffizienz bietet. Auf leistungsstarken Geräten wie dem Jetson Orin, das für KI-Anwendungen entwickelt wurde, kann vLLM seine Stärken voll ausspielen und ermöglicht schnelle und zuverlässige Textgenerierung sowie andere LLM-basierte Aufgaben. Die Investition in die Installation zahlt sich daher aus, da vLLM die Leistungsfähigkeit des Jetson Orin optimal nutzt und die Entwicklung und Bereitstellung von KI-Anwendungen erheblich vereinfacht.

Veröffentlicht in Allgemein