SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor

Nên chọn Ollama hay vLLM để chạy LLM server?

Chọn Ollama nếu bạn cần chạy model trên CPU hoặc máy cá nhân. Chọn vLLM nếu bạn cần throughput cao cho GPU. Bài viết so sánh chi tiết và cung cấp lệnh triển khai thực tế.

Ollama và vLLM, trong một đoạn

Ollama là trình quản lý model đi kèm server: nó tải các weight đã quantize, nạp chúng và trả lời trên 127.0.0.1:11434, bằng CPU nếu máy chỉ có CPU. vLLM là engine tối ưu throughput: nó giữ GPU luôn bận bằng cách chạy đồng thời nhiều request, nên không phù hợp với máy không có GPU. Quyết định chỉ có vậy. Một người trò chuyện với trợ lý local là tác vụ dành cho Ollama. Một ứng dụng phục vụ cả team là tác vụ dành cho vLLM.

Cả hai đều cung cấp HTTP API tương thích với OpenAI, nên chỉ cần đổi base URL là có thể chuyển client code giữa chúng. API không phải điểm khác biệt. Điểm khác biệt nằm ở cách hệ thống xử lý request thứ hai khi request thứ nhất vẫn đang generate token.

Ollama thực sự là gì

Ollama là một lớp tiện ích. Chỉ với một lệnh cài đặt, nó cung cấp registry model (ollama pull llama3.1:8b), nơi lưu trữ weights cục bộ, prompt chat, systemd service và HTTP API. Hầu hết model mà nó phục vụ là file GGUF, thường được quantize xuống 4-bit. Vì vậy, model 7B hoặc 8B thường chiếm khoảng 5 GB trên disk thay vì 16 GB. Quantization làm giảm lượng memory cần cho inference bằng CPU. Trên máy Mac dùng Apple Silicon, Ollama cũng có thể chạy model dựa trên safetensors thông qua engine MLX. Từ v0.40.0 (September 2026), các architecture được hỗ trợ sẽ tự động chạy trên MLX.

GGUF runner của Ollama được xây dựng trên llama.cpp, thư viện inference C++ giúp GGUF quantization trở nên thực tế trên phần cứng thông thường. Tính đến October 2026, Ollama hỗ trợ 2 engine là llama.cpp và MLX. Bản build cho Linux cũng hỗ trợ MLX inference với CUDA. Development guide bật backend đó bằng cmake -B build . -DOLLAMA_MLX_BACKENDS=cuda_v13, với CUDA 13+ và cuDNN 9+ là các prerequisite. Vì vậy, khi so sánh Ollama với llama.cpp, phần lớn mọi người đang so sánh một lớp giúp sử dụng dễ hơn với chính thành phần mà nó bọc bên ngoài.

Thiết kế của Ollama hướng đến một user. Tính đến October 2026, giá trị mặc định của OLLAMA_NUM_PARALLEL là 1. Điều này có nghĩa là một model chỉ xử lý 1 request tại một thời điểm, còn mọi request khác chờ trong queue mặc định có 512 entry (OLLAMA_MAX_QUEUE). Bạn có thể tăng thiết lập parallel. Phần bên dưới giải thích chi phí của việc này. Nếu chưa từng chạy Ollama, hãy bắt đầu với host Ollama trên VPS và giữ port 11434 đóng, vì local API không yêu cầu authentication.

vLLM thực sự là gì

vLLM chỉ là một inference server. Nó không quản lý model library, cung cấp một vllm chat client cho server đang chạy và không tự pull model khi nhận request. Bạn chỉ định một repository trên Hugging Face khi khởi động, vLLM load model đó rồi phục vụ model này cho đến khi bạn dừng process.

Đổi lại sự tập trung này là throughput cao. Có hai cơ chế thực hiện việc đó. PagedAttention lưu KV cache (key-value cache, trạng thái attention theo từng token mà model giữ cho mỗi request đang hoạt động) trong các block có kích thước cố định, tương tự cách operating system phân trang bộ nhớ. Request không còn cần một vùng nhớ liên tục lớn được cấp trước theo trường hợp xấu nhất. Vì vậy, phần memory trước đây bị giữ lại nhưng không được dùng có thể dành cho nhiều request đồng thời hơn. Continuous batching cho phép request mới tham gia batch đang chạy ở bước decoding tiếp theo, thay vì phải chờ batch hiện tại hoàn tất. Sequence hoàn tất sẽ rời batch ngay lập tức và slot của nó được cấp cho sequence khác.

Kết quả thực tế: trên một GPU, tăng từ 1 user đồng thời lên 30 user làm tổng số token mỗi giây tăng mạnh, trong khi tốc độ của từng user giảm ít hơn nhiều so với dự đoán. Với cấu hình mặc định của Ollama, tăng từ 1 user lên 30 user chỉ khiến 29 người phải chờ.

Batch liên tục tạo ra toàn bộ khác biệt

Hãy hình dung 5 request đến mỗi server cùng lúc trên phần cứng giống hệt nhau.

Ollama với thiết lập mặc định xử lý xong request thứ nhất, rồi mới xử lý request thứ hai, cứ như vậy. Người gọi thứ 5 phải chờ 4 lượt generation hoàn tất. Tổng throughput gần bằng tốc độ của 1 lượt generation, vì processor chỉ xử lý 1 sequence tại một thời điểm.

vLLM decode cả 5 sequence trong cùng 1 forward pass. Việc tạo 1 token cho 5 sequence chỉ tốn nhiều hơn không đáng kể so với tạo 1 token cho 1 sequence, vì phần tốn kém là đọc model weights từ memory và thao tác đọc này được chia sẻ cho toàn bộ batch. Đây cũng là nguyên nhân về memory bandwidth khiến CPU inference chậm: chi phí chủ yếu nằm ở việc di chuyển weights, không phải phép tính.

Bạn có thể đặt OLLAMA_NUM_PARALLEL=4 để có được một phần lợi ích này. Đổi lại là chi phí memory. Mỗi parallel slot cần một KV cache riêng, và Ollama nhân lượng context được cấp phát thay vì chia nhỏ lượng này: FAQ của Ollama cho biết RAM cần thiết tăng theo OLLAMA_NUM_PARALLEL lần OLLAMA_CONTEXT_LENGTH. Vì vậy, 4 request chạy song song với model được cấu hình cho 8192 token vẫn giữ 8192 token cho mỗi request, nhưng máy phải chứa cache cho tổng cộng 32768 token. Giá trị 8192 này cũng là một lựa chọn chứ không phải giá trị cố định, nên tăng num_ctx và tính lượng RAM cần dùng là bước quyết định 4 slot có thể chạy cùng lúc hay không. Paged cache của vLLM tránh việc phải cấp phát trước toàn bộ context window cho từng slot, vì các block được cấp cho request khi request thực sự tăng lên. Dù dùng cách nào, giới hạn về số người mà một máy có thể phục vụ đồng thời vẫn phụ thuộc vào kích thước KV cache, chi phí prefill và độ dài queue. Đây là lý do một server chạy ổn cho 1 người lại trở nên ì ạch khi có 5 người.

Cài đặt và phục vụ bằng Ollama

curl -fsSL https://ollama.com/install.sh | sh
ollama pull llama3.1:8b
ollama run --verbose llama3.1:8b "Write two sentences about Linux."

Script cài đặt tạo một system user ollama, cài binary và đăng ký ollama.service bind vào 127.0.0.1:11434. Dòng eval rate do --verbose in ra là số token mỗi giây thực tế trên máy đó. Hãy tin số liệu này hơn mọi con số được công bố. Một lần đo từ một prompt chỉ là điểm bắt đầu, không phải con số về năng lực xử lý. Vì vậy, đo số token mỗi giây qua nhiều mức concurrency mới cho biết máy có chịu được tải bạn thực sự dự kiến hay không, và thuê GPU có tiết kiệm hơn trả tiền theo token hay không.

Để tăng concurrency, hãy dùng systemd drop-in để lần upgrade không ghi đè thay đổi này:

sudo systemctl edit ollama.service
[Service]
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_KEEP_ALIVE=30m"
sudo systemctl restart ollama
ollama ps

ollama ps cho biết cấu hình nào đang được nạp, còn cột PROCESSOR cho biết trạng thái thực tế. 100% CPU nghĩa là không có GPU được sử dụng. Đây là nguyên nhân thực tế của phần lớn các trường hợp Ollama chạy chậm. Dòng OLLAMA_KEEP_ALIVE=30m trong drop-in cũng quan trọng trên máy ít tải, vì mặc định sẽ unload model sau 5 phút không có request. Giữ model trong memory giữa các request giúp prompt đầu tiên sau khoảng nghỉ tối đa 30 phút không phải chịu lại toàn bộ thời gian load. Nếu các khoảng nghỉ của bạn dài hơn, hãy đặt giá trị dài hơn.

Cài đặt và phục vụ bằng vLLM

Các bản build GPU của vLLM cần Linux. macOS trên Apple Silicon chỉ hỗ trợ CPU với wheel dựng sẵn trong bản release 0.32.0. Khả năng tăng tốc GPU trên các máy Mac này đến từ vLLM-Metal, một plugin do cộng đồng duy trì và được xây dựng trên MLX. Với Python, bản release hiện tại (0.32.0, tháng 10 năm 2026) hỗ trợ các phiên bản từ 3.11 đến 3.14, và hướng dẫn cài đặt cũng liệt kê cùng khoảng này. Python 3.10 đã bị loại bỏ trong 0.32.0, vì vậy 3.12, được dùng bên dưới, là lựa chọn an toàn. Cài đặt nó trong một virtual environment riêng vì vLLM sẽ cài một bản PyTorch cụ thể:

uv venv --python 3.12 --seed
source .venv/bin/activate
uv pip install vllm --torch-backend=auto
vllm download-kernels

Dòng cuối có trong hướng dẫn cài đặt NVIDIA của vLLM tính đến tháng 10 năm 2026. Dòng này cài các kernel đã biên dịch sẵn của FlashInfer. Nếu không có chúng, vLLM sẽ tải xuống và biên dịch kernel khi khởi động. Theo hướng dẫn, việc này có thể mất thêm vài phút trên GPU Hopper và các thế hệ mới hơn. Chạy lại lệnh này sau mỗi lần nâng cấp vLLM vì FlashInfer sẽ không import được khi kernel không khớp.

Sau đó, phục vụ một model. Tên này là repository id trên Hugging Face, không phải short tag:

vllm serve Qwen/Qwen2.5-1.5B-Instruct

Lần đầu khởi động sẽ chậm vì vLLM phải tải weights rồi profile GPU để xác định có thể chứa bao nhiêu block KV cache. vLLM lắng nghe trên port 8000. Kiểm tra nó trước khi viết code cho client:

curl http://localhost:8000/v1/models
curl http://localhost:8000/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{"model": "Qwen/Qwen2.5-1.5B-Instruct", "messages": [{"role": "user", "content": "Who won the world series in 2020?"}]}'

Nếu máy đã có Docker, image chính thức sẽ loại bỏ phần xử lý dependency của CUDA:

docker run --runtime nvidia --gpus all \
    -v ~/.cache/huggingface:/root/.cache/huggingface \
    --env "HF_TOKEN=$HF_TOKEN" \
    -p 8000:8000 \
    --ipc=host \
    vllm/vllm-openai:latest \
    --model Qwen/Qwen3-0.6B

--ipc=host cho phép container truy cập shared memory của host; tăng --shm-size cũng là một lựa chọn. PyTorch truyền tensor giữa các process thông qua shared memory, đặc biệt khi inference theo tensor parallel.

Các flag quan trọng nhất trong production là --max-model-len (context window mà bạn chấp nhận trả chi phí), --gpu-memory-utilization (tỷ lệ GPU mà vLLM được phép sử dụng; mặc định là 0.92 tính đến tháng 10 năm 2026), --tensor-parallel-size để chia một model trên nhiều GPU, và --api-key.

Authentication chỉ cần 1 flag trên vLLM và không có trên local API của Ollama

vLLM bắt buộc bearer token nếu bạn cung cấp token:

vllm serve Qwen/Qwen2.5-1.5B-Instruct --api-key token-abc123

Giá trị tương tự có thể lấy từ biến môi trường VLLM_API_KEY. Request đến /v1 nếu không có token sẽ trả về HTTP 401. Tuy nhiên, key này không bảo vệ toàn bộ server. Security guide của vLLM và authentication code trong source 0.32.0 chỉ áp dụng cho các endpoint dưới các path prefix /v1, /v2, /inference và /cohere. Phần help text --api-key trên trang vllm serve chỉ liệt kê 3 prefix đầu tiên, nhưng code kiểm tra cả 4 prefix. Cả guide và help text đều nói rằng các endpoint khác, đáng chú ý nhất là /invocations, cung cấp cùng inference như /v1, không được authentication bảo vệ. Đây là lý do đủ để không publish port 8000 trên public interface. Security guide của vLLM cũng để reverse proxy phía trước xử lý rate limiting. Ngoài ra, token gửi qua HTTP không mã hóa có thể bị đọc trên đường truyền. Tuy vậy, flag này vẫn có nghĩa là server có khái niệm về caller.

Local API của Ollama không yêu cầu authentication. Cloud model, việc publish model và download private model yêu cầu sign-in. Truy cập API trực tiếp đến ollama.com yêu cầu API key. Bất kỳ process nào có thể reach port 11434 đều có thể chạy, pull hoặc delete model. Hãy giữ API trên loopback và truy cập qua WireGuard VPN do bạn tự host, hoặc qua reverse proxy có authentication và thực hiện TLS termination (transport layer security).

Phần cứng: mỗi công cụ cần gì

Ollama chạy trên CPU. Một model được quantize ở mức 4-bit cần khoảng nửa gigabyte RAM cho mỗi tỷ parameter, cộng thêm khoảng 1 gigabyte overhead khi runtime và nhiều hơn tùy context. Vì vậy, model 3B cần khoảng 4 GB RAM trống, còn model 8B cần khoảng 8 GB. Tốc độ trên vCPU dùng chung thường chỉ từ một chữ số đến mức thấp của hai chữ số token mỗi giây. Đây là giới hạn băng thông bộ nhớ, không phải lỗi cấu hình, và không có flag nào khắc phục được. Để xem các con số này trên một release cụ thể thay vì dựa vào quy tắc ước lượng, chạy Nemotron 3.5 Lightning trên VPS sẽ xác định chính xác tag cần pull, lượng RAM model chiếm sau khi load, và liệu CPU-only có đủ nhanh để sử dụng thường xuyên hay không.

vLLM giả định bạn có GPU. Luồng mặc định của nó phục vụ weight chưa quantize ở precision 16-bit, tương đương khoảng 2 GB cho mỗi tỷ parameter. Model 8B cần khoảng 16 GB video memory chỉ cho weight, chưa tính KV cache vốn cung cấp khả năng xử lý đồng thời mà bạn cài vLLM để có. Trên card 24 GB, phần bộ nhớ còn lại đủ để làm cache. Trên card 16 GB thì không đủ. Khi đó, bạn phải chọn model nhỏ hơn, truyền --quantization (kèm một quantized checkpoint hoặc để quantize weight full-precision tại thời điểm load), hoặc chuyển một phần weight vào system RAM bằng --cpu-offload-gb. Cách này giữ nguyên precision của weight nhưng chậm hơn, vì các weight đó phải được chuyển sang GPU trong mỗi forward pass. Có CPU backend với các wheel riêng, nhưng dùng nó sẽ mất đi lý do chính để chạy vLLM.

Vì vậy, phần cứng thường quyết định câu trả lời cho câu hỏi về software. Không có GPU thì dùng Ollama. Nếu GPU thuê chỉ sử dụng 5 phần trăm vì các request đang bị xử lý tuần tự thì dùng vLLM.

Chọn công cụ cho workload

  • Một người dùng, một CPU VPS, soạn thảo và tóm tắt: Ollama. Tốc độ đủ dùng và không có lựa chọn nào đơn giản hơn.
  • Trợ lý lập trình hoặc MCP server kết nối các công cụ của bạn với model local mà chỉ mình bạn gọi: Ollama. Workload thực tế chỉ có một request chạy đồng thời.
  • So sánh 5 model trong tuần này: Ollama. Việc pull và xóa các model có tag đúng với điểm mạnh của nó, còn vLLM cần restart process cho từng model.
  • Một app nội bộ, sản phẩm chat hoặc pipeline retrieval có người dùng thực: vLLM. Đây là trường hợp batching giúp GPU phát huy hiệu quả tương xứng với chi phí.
  • Một batch job chấm điểm 100000 tài liệu qua đêm: vLLM, với --max-num-seqs cao. Chỉ throughput mới quan trọng; latency của từng tài liệu không quan trọng.
  • Một nền tảng agent trong đó nhiều AI agent tự host cùng lúc gửi request đến model: vLLM, vì traffic của agent có tính bursty và bản chất là chạy song song.

Các dạng lỗi và những chuỗi bạn sẽ thấy

vLLM từ chối khởi động với lỗi KV cache. Message hiển thị cả 2 giá trị:

ValueError: To serve at least one request with the model's max seq len (32768), (4.00 GiB KV cache is needed, which is larger than the available KV cache memory (1.00 GiB). Based on the available memory, the estimated maximum model length is 8192. Try increasing `gpu_memory_utilization` (which also controls CPU memory on the CPU backend) or decreasing `max_model_len` when initializing the engine. See https://docs.vllm.ai/en/latest/configuration/conserving_memory/ for more details.

Model khai báo context window lớn hơn memory còn lại sau khi load weights. Giảm giá trị này bằng --max-model-len 8192, hoặc tăng --gpu-memory-utilization nếu không có process nào khác đang dùng card.

Ollama in Killed giữa lúc generation. Linux out-of-memory killer đã dừng process vì model cần nhiều RAM hơn dung lượng của máy. Xác nhận bằng sudo dmesg | grep -i oom. Cách sửa là dùng model nhỏ hơn hoặc quantize mạnh hơn, không phải thay đổi một setting.

Ollama trả lời bình thường khi chạy riêng nhưng bị đứng khi có tải. Không có error nào xuất hiện. Request chỉ mất nhiều thời gian hơn khi số caller tăng, vì OLLAMA_NUM_PARALLEL=1 đang xử lý chúng tuần tự. Câu trả lời dài làm queue tệ hơn. Một caller chiếm slot duy nhất cho đến khi model quyết định dừng sẽ chặn mọi caller phía sau. Vì vậy, giới hạn câu trả lời bằng num_predict sẽ đặt giới hạn thời gian mỗi turn có thể giữ server. Bạn có thể tăng thiết lập parallel và chấp nhận lượng RAM bổ sung mà context của mỗi slot cần, hoặc chuyển workload sang vLLM.

vLLM trả về 401 cho mọi lần gọi /v1. Bạn khởi động nó bằng --api-key nhưng client không gửi header Authorization. Hầu hết OpenAI client library sẽ gửi giá trị bạn truyền làm key, vì vậy hãy đặt key ở đó thay vì bỏ flag.

vLLM báo không tìm thấy model. Ollama pull model theo yêu cầu, còn vLLM thì không. Trường model trong request body phải khớp với repository id bạn dùng khi khởi động, hoặc khớp với giá trị của --served-model-name nếu bạn đã đặt giá trị này. Xác nhận chuỗi chính xác bằng curl http://localhost:8000/v1/models.

Chạy cả hai là một lựa chọn hợp lý

Hai lựa chọn này không loại trừ nhau. Một mô hình triển khai phổ biến là chạy vLLM trên một instance có GPU để phục vụ ứng dụng, đồng thời chạy Ollama trên VPS thông thường để phục vụ các script cục bộ, cron job và việc thử các bản phát hành model mới. Cả hai endpoint đều tương thích với OpenAI, nên chỉ cần một client library và chuyển đổi base URL là đủ. Kiểm soát chi phí quan trọng hơn việc chọn engine nào, vì GPU nhàn rỗi vẫn bị tính phí như khi đang hoạt động. Giữ chi phí của agent và inference ở mức dự đoán được là một quy trình riêng, không phụ thuộc vào việc chọn server.

FAQ

vLLM có nhanh hơn Ollama không?

Với một request trên cùng GPU, chênh lệch không lớn vì cả hai đều thực hiện cùng phép tính. Với nhiều request đồng thời, vLLM nhanh hơn đáng kể vì continuous batching giải mã mọi sequence đang hoạt động trong cùng một forward pass, còn cấu hình mặc định của Ollama chạy lần lượt từng sequence. Trên máy chỉ có CPU, cả hai đều có đường chạy inference được hỗ trợ, trong đó vLLM dùng các CPU wheel riêng.

vLLM có chạy được nếu không có GPU không?

Có, thông qua CPU backend. Các wheel tiêu chuẩn nhắm đến GPU NVIDIA hoặc AMD, còn lý do vLLM tồn tại — giữ accelerator luôn bận với các request được batch — không còn ý nghĩa trên CPU. vLLM có CPU backend, với các wheel riêng cho x86 và Arm. Nếu cần inference thực sự trên CPU, hãy dùng Ollama hoặc llama.cpp trực tiếp.

Ollama và llama.cpp khác nhau như thế nào?

llama.cpp là inference library, còn GGUF là định dạng weight đã quantize của nó. Ollama dùng llama.cpp để inference với GGUF và bổ sung model registry, download có tag, quản lý model và systemd unit. Ollama cũng cung cấp MLX engine để chạy model dựa trên safetensors trên Apple Silicon và hỗ trợ các bản build CUDA trên Linux, vì vậy phần nền của hai công cụ không phải lúc nào cũng giống hệt nhau.

vLLM cần bao nhiêu GPU memory cho model 8B?

Ở precision 16-bit, riêng weight đã chiếm khoảng 16 GB, tương đương khoảng 2 GB cho mỗi 1 tỷ parameter, và KV cache cần thêm dung lượng. Card 24 GB là đủ thoải mái. Card 16 GB cần model đã quantize, model nhỏ hơn hoặc --cpu-offload-gb để chuyển một phần weight vào system RAM, đổi lại tốc độ sẽ giảm. vLLM sử dụng một phần GPU memory được đặt bằng --gpu-memory-utilization, mặc định là 0.92 tính đến tháng 10 năm 2026.

Tôi có cần sửa code ứng dụng khi chuyển đổi giữa hai công cụ không?

Thông thường chỉ cần đổi base URL, API key và tên model. Ollama cung cấp OpenAI-compatible surface tại http://127.0.0.1:11434/v1 và bỏ qua key, còn vLLM cung cấp http://localhost:8000/v1 và kiểm tra key trên các route /v1 nếu bạn đặt key. Tên model có dạng khác nhau: llama3.1:8b đối với Ollama, còn vLLM dùng repository id đầy đủ như Qwen/Qwen2.5-1.5B-Instruct.

Bài viết này có hữu ích không?