AI Engineering · Chip Huyen · Chương 9AI Engineering · Chip Huyen · Chương 9AI Engineering · Chip Huyen · Chapter 9
Chương 9 · Tối ưu suy luậnChương 9 · Tối ưu suy luậnChapter 9 · Inference Optimization

Nhanh hơn và rẻ hơnLàm cho máy trả lời nhanh hơnFaster and cheaper

Tám chương trước bàn chuyện làm mô hình tốt hơn. Chương này đổi trục: làm nó nhanh hơn và rẻ hơn. Huyen mở đầu bằng một lời cảnh báo rất thực tế — một mô hình dù giỏi đến mấy, nếu quá chậm thì người dùng mất kiên nhẫn, hoặc tệ hơn, dự đoán của nó trở nên vô dụng; còn nếu quá đắt thì lợi ích thu về không bõ.1 Tối ưu suy luận vì thế không phải việc làm đẹp cuối dự án, mà là điều kiện để sản phẩm tồn tại.

Từ đầu sách tới giờ ta toàn học cách làm máy trả lời đúng. Bài này học cách làm máy trả lời nhanh và đỡ tốn tiền. Vì máy trả lời đúng mà phải chờ cả phút thì chẳng ai dùng, còn trả lời nhanh mà tốn quá nhiều tiền thì cũng không làm nổi. Nhớ nhé: nhanh và rẻ cũng là một phần của "hay".

The previous chapters were about making models better. This one switches axis: making them faster and cheaper. Huyen opens with a blunt practical warning — no matter how good your model is, if it is too slow your users lose patience, or worse, its predictions become useless; and if it is too expensive, the return on investment is not worth it.1 Inference optimization is therefore not end-of-project polish, it is a condition for the product to exist at all.

∴
Luận đề của chương Ý chính của bài The chapter's thesis

Tối ưu là việc tìm ra nút thắt rồi gỡ đúng nút thắt đó — và nó có thể diễn ra ở ba cấp: mô hình, phần cứng, và dịch vụ suy luận. Huyen ví von: tối ưu cấp mô hình là làm mũi tên tốt hơn, tối ưu cấp phần cứng là rèn một cung thủ khỏe hơn, còn tối ưu cấp dịch vụ là chỉnh lại toàn bộ quy trình bắn, gồm cả cây cung lẫn điều kiện ngắm.1 Vì hai nút thắt lớn của mô hình ngôn ngữ nằm ở giải mã tự hồi quy và cơ chế attention, phần lớn kỹ thuật trong chương xoay quanh đúng hai chỗ ấy.

Muốn làm gì đó nhanh hơn, trước hết phải biết nó đang bị kẹt ở đâu — giống như muốn hết tắc đường thì phải tìm đúng chỗ tắc. Máy trả lời chậm có thể vì nó phải tính quá nhiều, hoặc vì nó phải khuân dữ liệu đi lại quá nhiều. Nhớ nhé: sửa đúng chỗ kẹt mới nhanh, sửa lung tung thì chỉ tốn công.

Optimization is about identifying bottlenecks and addressing them — and it can happen at three levels: the model, the hardware, and the inference service. Huyen's analogy: model-level optimization is like crafting better arrows, hardware-level optimization is like training a stronger archer, and service-level optimization is like refining the whole shooting process, bow and aiming conditions included.1 Because the two big bottlenecks of a language model sit in autoregressive decoding and the attention mechanism, most of the chapter's techniques target exactly those two places.

Mục 01 · Nút thắtMục 01 · Máy kẹt ở đâuPart 01 · Bottlenecks

Hai kiểu kẹtMáy chậm vì hai lý doTwo ways to be stuck

Huyen đặt nền cho cả chương bằng một phân biệt tưởng nhỏ mà quyết định mọi thứ về sau: một tác vụ chậm vì nó phải tính quá nhiều, hay chậm vì nó phải chuyển dữ liệu quá nhiều? Hai nguyên nhân ấy cần hai loại thuốc khác nhau — và với mô hình ngôn ngữ tự hồi quy, hai nguyên nhân ấy xuất hiện ở hai pha khác nhau của cùng một lần trả lời.1

Hình dung một quán ăn chậm. Có thể vì đầu bếp nấu chậm — tay nghề có hạn. Cũng có thể vì đầu bếp nấu rất nhanh nhưng nguyên liệu để tận kho xa, chạy đi chạy lại mất thời gian. Hai lý do khác nhau thì cách chữa cũng khác nhau.

Huyen grounds the whole chapter in a distinction that looks small but decides everything downstream: is a task slow because it has too much to compute, or because it has too much data to move? The two causes need different medicine — and in an autoregressive language model, the two causes show up in two different phases of the very same response.1

Tối ưu là tìm nút thắt rồi gỡ đúng nút thắt đó — như người quy hoạch giao thông phải tìm ra điểm ùn tắc trước khi mở đường.1

Muốn hết tắc đường, phải biết đang tắc ở khúc nào đã.

Optimization is about identifying bottlenecks and addressing them — the way a city planner must first find the congestion point before widening any road.1

Khái niệm compute-bound và memory bandwidth-bound đến từ bài báo “Roofline” (Williams và cộng sự, 2009). Về mặt toán học, một phép tính được xếp vào loại nào là tùy vào arithmetic intensity của nó — số phép tính số học trên mỗi byte truy cập bộ nhớ.2 Các công cụ đo như NVIDIA Nsight vẽ ra biểu đồ roofline đúng để trả lời câu hỏi này.

Compute-boundThời gian hoàn tất bị quyết định bởi khối lượng tính toán. Ví dụ của Huyen: giải mã mật khẩu.1Chậm vì phải tính quá nhiều.Time-to-complete is set by the computation required. Huyen's example: password decryption.1
Bandwidth-boundBị chặn bởi tốc độ chuyển dữ liệu trong hệ thống, ví dụ giữa bộ nhớ và bộ xử lý.1Chậm vì phải khuân đồ đi lại quá xa.Constrained by the data transfer rate inside the system, e.g. between memory and processors.1
PrefillMô hình xử lý toàn bộ token đầu vào song song → compute-bound.1Máy đọc hết câu hỏi một lượt.The model processes the input tokens in parallel → compute-bound.1
DecodeMô hình sinh từng token một, phải nạp ma trận trọng số lớn vào GPU → bandwidth-bound.1Máy viết câu trả lời từng chữ một.The model generates one token at a time, loading large weight matrices into the GPU → memory bandwidth-bound.1
  1. 01
    Compute-bound vs memory bandwidth-bound

    Kẹt tính toán — kẹt băng thôngNấu chậm hay chạy kho chậmCompute-bound vs bandwidth-bound

    Một tác vụ compute-bound bị quyết định bởi lượng tính toán cần làm; một tác vụ memory bandwidth-bound bị quyết định bởi tốc độ dữ liệu di chuyển trong hệ thống — ví dụ khi dữ liệu nằm ở bộ nhớ CPU còn mô hình chạy trên GPU.1 Kiến trúc và khối lượng công việc khác nhau cho ra nút thắt khác nhau: suy luận của mô hình sinh ảnh như Stable Diffusion thường compute-bound, còn suy luận của mô hình ngôn ngữ tự hồi quy thường bandwidth-bound.1

    Hai cái chậm khác nhau. Một là "đầu bếp nấu chậm": phải tính nhiều quá. Hai là "kho ở xa": tính thì nhanh nhưng phải chạy đi lấy nguyên liệu liên tục. Máy vẽ tranh thường kẹt kiểu một, còn máy viết chữ thường kẹt kiểu hai. Nhớ nhé: chậm vì tính nhiều khác với chậm vì khuân nhiều.

    A compute-bound task is determined by the computation it needs; a memory bandwidth-bound task is determined by how fast data moves inside the system — for instance when data sits in CPU memory while the model runs on GPUs.1 Different architectures and workloads produce different bottlenecks: inference for image generators like Stable Diffusion is typically compute-bound, while inference for autoregressive language models is typically memory bandwidth-bound.1

    Thấy nó ở đâuWhere you see it Khi bạn nâng cấp lên con chip nhiều FLOP/s hơn mà độ trễ gần như không đổi — rất có thể bạn đang kẹt băng thông chứ không kẹt tính toán, và tiền chi thêm đã đi sai chỗ. Mua bếp xịn hơn mà quán vẫn chậm — vì vấn đề nằm ở cái kho, không phải cái bếp. When you upgrade to a chip with more FLOP/s and latency barely moves, you were probably bandwidth-bound rather than compute-bound — and the extra money went to the wrong place.

    Nhập nhằng thuật ngữ

    Huyen dành hẳn một hộp cảnh báo cho chữ memory-bound: có người dùng nó để chỉ giới hạn dung lượng bộ nhớ (lỗi OOM quen thuộc), có người dùng nó để chỉ giới hạn băng thông. Bà lập luận rằng giới hạn dung lượng thường gỡ được bằng cách chia nhỏ tác vụ, nên rốt cuộc nó cũng quy về băng thông.1 Chính bài báo “Roofline” dùng memory-bound theo nghĩa bandwidth-bound; vì vậy trang này theo cách gọi đầy đủ của sách — memory bandwidth-bound — thay vì âm thầm chọn một nghĩa.12

    Thuốc nào cho bệnh nào

    Tác vụ compute-bound được tăng tốc bằng cách trải ra nhiều chip hơn hoặc dùng chip nhiều FLOP/s hơn. Tác vụ bandwidth-bound được tăng tốc bằng chip có băng thông cao hơn.1 Tại thời điểm sách viết, do sự phổ biến của kiến trúc transformer và giới hạn của công nghệ tăng tốc hiện có, phần lớn workload AI và dữ liệu đang là bandwidth-bound.1

  2. 02
    Prefill and decode

    Prefill và decode — một câu trả lời, hai tính cáchĐọc đề và viết bàiPrefill and decode — one response, two personalities

    Suy luận của mô hình ngôn ngữ dựa trên transformer gồm hai bước. Prefill: mô hình xử lý các token đầu vào song song, giới hạn bởi số phép tính phần cứng làm được trong một khoảng thời gian — nên nó compute-bound. Decode: mô hình sinh từng token một, mỗi bước phải nạp những ma trận lớn vào GPU, giới hạn bởi tốc độ nạp dữ liệu — nên nó bandwidth-bound.1

    Máy trả lời qua hai chặng. Chặng một là đọc đề: nó đọc hết câu hỏi của bạn cùng một lúc, rất nhanh. Chặng hai là viết bài: nó viết từng chữ một, chữ sau phải chờ chữ trước. Nhớ nhé: đọc đề thì đọc một lượt, viết bài thì viết từng chữ — nên chặng hai bao giờ cũng lâu hơn.

    Inference for a transformer-based language model has two steps. Prefill: the model processes input tokens in parallel, limited by how many operations the hardware can execute in a given time — so it is compute-bound. Decode: the model generates one token at a time, each step loading large matrices into the GPU, limited by how fast data can be loaded — so it is memory bandwidth-bound.1

    Thấy nó ở đâuWhere you see it Đây là lý do gần như mọi chỉ số và mọi kỹ thuật ở phần sau đều tách đôi: một nửa nói về prefill, một nửa nói về decode. Kể cả việc tách hai pha ra hai cụm máy riêng cũng bắt nguồn từ đây.1 Vì hai chặng khác nhau nên người ta đo riêng, chữa riêng, thậm chí cho chạy trên hai máy riêng. This is why nearly every metric and technique later in the chapter splits in two: half is about prefill, half about decode. Even running the two phases on separate machines starts here.1

    Điều gì quyết định tỉ lệ

    Các yếu tố chi phối lượng tính toán prefill và decode — và do đó chi phối nút thắt của máy chủ — gồm độ dài ngữ cảnh, độ dài đầu ra, và chiến lược gộp lô yêu cầu. Ngữ cảnh dài thường đẩy workload về phía bandwidth-bound, nhưng các kỹ thuật tối ưu khéo léo có thể gỡ bỏ nút thắt ấy.1

    Chi phí lệch hẳn về đầu ra

    Ở các nhà cung cấp API, một token đầu ra tốn khoảng gấp hai tới bốn lần một token đầu vào. Trong một thí nghiệm của Anyscale, một token đầu ra đơn lẻ có tác động lên độ trễ tương đương khoảng 100 token đầu vào.3 Cải thiện quá trình sinh tự hồi quy dù chỉ vài phần trăm cũng đáng giá.

  3. 03
    Inference server and inference service

    Máy chủ suy luận và dịch vụ suy luậnAi là người chạy cái máyInference server and inference service

    Thành phần chạy mô hình trong môi trường sản xuất gọi là inference server: nó chứa các mô hình có sẵn, có quyền truy cập phần cứng, và dựa trên yêu cầu từ ứng dụng mà cấp phát tài nguyên để chạy mô hình phù hợp. Nó là một phần của inference service rộng hơn — thứ chịu trách nhiệm nhận, định tuyến và có thể tiền xử lý yêu cầu trước khi chúng tới máy chủ.1

    Có hai vai. Một là cái bếp thật sự nấu món — nó giữ công thức và có bếp lò. Hai là cả cái nhà hàng bao quanh: người nhận đơn, người chia đơn về đúng bếp, người mang món ra. Nhớ nhé: chạy được mô hình mới chỉ là cái bếp, còn cả nhà hàng nữa mới thành dịch vụ.

    The component that runs model inference in production is called an inference server: it hosts the available models, has access to the necessary hardware, and allocates resources to run the right model based on application requests. It is part of a broader inference service, which also receives, routes and possibly preprocesses requests before they reach the server.1

    Thấy nó ở đâuWhere you see it Các model API như của OpenAI hay Google chính là dịch vụ suy luận. Nếu bạn dùng chúng, bạn sẽ không phải tự cài đặt phần lớn kỹ thuật trong chương này; nếu bạn tự host mô hình, bạn chịu trách nhiệm xây, tối ưu và bảo trì toàn bộ dịch vụ ấy.1 Dùng API của người ta thì họ lo hết. Tự chạy máy thì mình phải tự lo. Model APIs from OpenAI or Google are inference services. If you use them, you will not implement most of the techniques in this chapter; if you host a model yourself, you own building, optimising and maintaining that service.1
  4. 04
    Online and batch inference APIs

    API trực tuyến và API theo lôHàng gấp và hàng thườngOnline and batch APIs

    Nhiều nhà cung cấp mở hai loại API. Online API tối ưu cho độ trễ: yêu cầu được xử lý ngay khi tới. Batch API tối ưu cho chi phí: chấp nhận độ trễ cao hơn để mở đường cho nhiều kỹ thuật tối ưu hơn, gồm gộp lô và dùng phần cứng rẻ hơn. Tại thời điểm sách viết, cả Google Gemini lẫn OpenAI đều bán batch API với mức giảm giá 50% và thời gian hoàn tất tính bằng giờ thay vì giây hay phút.14

    Giống gửi bưu kiện: có dịch vụ hỏa tốc và dịch vụ thường. Hỏa tốc thì tới ngay nhưng đắt; dịch vụ thường rẻ hơn một nửa nhưng phải chờ vài tiếng. Nhớ nhé: việc nào không gấp thì gửi đường thường cho rẻ.

    Many providers offer two API types. Online APIs optimise for latency: requests are processed as soon as they arrive. Batch APIs optimise for cost: higher latency opens the door to a broader range of optimisations, including batching requests and using cheaper hardware. As of the book's writing, both Google Gemini and OpenAI offered batch APIs at a 50% cost reduction with turnaround in the order of hours rather than seconds or minutes.14

    Thấy nó ở đâuWhere you see it Huyen liệt kê những việc hợp với batch API: sinh dữ liệu tổng hợp, báo cáo định kỳ (tóm tắt tin nhắn Slack, phân tích cảm xúc các lượt nhắc thương hiệu), xử lý tài liệu khi tiếp nhận khách hàng mới, xử lý lại toàn bộ dữ liệu khi đổi mô hình, và cập nhật cơ sở tri thức bằng cách đánh chỉ mục lại.1 Việc không ai ngồi chờ — như tóm tắt cả đống tài liệu qua đêm — thì gửi đường thường. Huyen lists what fits a batch API: synthetic data generation, periodic reporting (summarising Slack messages, sentiment analysis of brand mentions), onboarding customers whose documents must all be processed, reprocessing everything for a model migration, and knowledge base re-indexing.1

    Khác với batch của ML cổ điển

    Huyen cảnh báo rằng batch API của mô hình nền tảng khác hẳn batch inference trong ML truyền thống. Ở ML truyền thống, batch nghĩa là tính trước dự đoán khi yêu cầu chưa tới — làm được với hệ gợi ý vì đầu vào hữu hạn và dự đoán được. Với mô hình nền tảng, đầu vào mở, khó đoán hết prompt của người dùng.1

    Chế độ streaming

    API thường trả về câu trả lời hoàn chỉnh, nhưng với giải mã tự hồi quy thì chờ rất lâu. Nhiều online API cung cấp streaming mode, trả từng token ngay khi sinh ra, rút ngắn thời gian chờ token đầu. Cái giá là bạn không kịp chấm điểm câu trả lời trước khi người dùng nhìn thấy nó — dù vẫn có thể sửa hoặc gỡ về sau khi phát hiện rủi ro.1

Mục 02 · Chỉ sốMục 02 · Đo tốc độPart 02 · Metrics

Đo trước khi tối ưuĐo xem máy nhanh chậm ra saoMeasure before you optimise

Từ phía người dùng, trục trung tâm là độ trễ — còn chất lượng câu trả lời, Huyen nhắc, là thuộc tính của mô hình chứ không phải của dịch vụ suy luận. Nhưng người làm ứng dụng còn phải nhìn thêm thông lượng và mức tận dụng, vì chính hai thứ đó định ra chi phí.1

Muốn biết máy nhanh hay chậm thì phải đo. Người dùng quan tâm: bao lâu thì có chữ đầu tiên, và chữ sau ra nhanh không. Người làm chủ còn quan tâm: mỗi giờ phục vụ được bao nhiêu người, và cỗ máy đắt tiền kia có đang được dùng hết công suất không.

From the user's perspective the central axis is latency — response quality, Huyen notes, is a property of the model itself, not of the inference service. But application developers must also watch throughput and utilization, because those two determine cost.1

Độ trễ là một phân phối, không phải một con số. Vì vậy trung bình có thể đánh lừa bạn, còn phân vị mới nói thật.1

Đừng chỉ nhìn số trung bình — một khách phải chờ rất lâu sẽ bị con số trung bình che mất.

Latency is a distribution, not a number. Averages can mislead you; percentiles tell the truth.1

Huyen đưa một ví dụ rất gọn: mười yêu cầu có TTFT lần lượt 100, 102, 100, 100, 99, 104, 110, 90, 3.000 và 95 ms. Trung bình là 390 ms — khiến dịch vụ của bạn trông chậm hơn thực tế rất nhiều. Có thể một lỗi mạng đã làm chậm một yêu cầu, hoặc một prompt đặc biệt dài đã kéo dài pha prefill; dù là gì thì bạn cũng nên đi tìm hiểu.1 Các phân vị nên theo dõi thường là p50, p90, p95 và p99; vẽ TTFT theo độ dài đầu vào cũng rất có ích.

TTFTTime to first token — bao lâu thì token đầu tiên xuất hiện; tương ứng với pha prefill và phụ thuộc độ dài đầu vào.1Bao lâu thì có chữ đầu tiên.Time to first token — how quickly the first token appears; corresponds to the prefill step and depends on input length.1
TPOTTime per output token — mỗi token sau token đầu mất bao lâu. Nếu mỗi token mất 100 ms thì câu trả lời 1.000 token mất 100 giây.1Mỗi chữ tiếp theo mất bao lâu.Time per output token — how long each token after the first takes. At 100 ms per token, a 1,000-token response takes 100 s.1
Tổng độ trễTotal latency= TTFT + TPOT × số token đầu ra.1Bằng thời gian chờ chữ đầu, cộng thời gian viết nốt phần còn lại.= TTFT + TPOT × number of output tokens.1
ThroughputSố token đầu ra mỗi giây dịch vụ sinh được, tính trên toàn bộ người dùng và yêu cầu. Thường đo bằng tokens/s (TPS).1Một giây cả hệ thống viết được bao nhiêu chữ.Output tokens per second across all users and requests, usually measured in tokens/s (TPS).1
GoodputSố yêu cầu mỗi giây thỏa mãn SLO. Nếu dịch vụ hoàn tất 100 yêu cầu/phút nhưng chỉ 30 đạt SLO thì goodput là 30.1Số khách được phục vụ đúng hẹn, không tính số khách bị trễ.Requests per second that satisfy the SLO. If a service completes 100 requests/minute but only 30 meet the SLO, its goodput is 30.1
MFUModel FLOP/s Utilization — tỉ lệ giữa thông lượng quan sát được và thông lượng lý thuyết tối đa khi chip chạy ở peak FLOP/s.1Cỗ máy tính được bao nhiêu phần trăm sức của nó.Model FLOP/s Utilization — observed throughput relative to the theoretical maximum at the chip's peak FLOP/s.1
MBUModel Bandwidth Utilization = (số tham số × byte/tham số × tokens/s) / băng thông lý thuyết.1Đường ống chuyển dữ liệu đang dùng hết mấy phần.Model Bandwidth Utilization = (parameter count × bytes/param × tokens/s) / theoretical bandwidth.1
  1. 05
    TTFT and TPOT — the same total, two experiences

    Cùng một tổng, hai trải nghiệmChờ lâu ở đầu hay chờ lai raiSame total, two experiences

    Hai ứng dụng có tổng độ trễ như nhau vẫn có thể cho trải nghiệm rất khác, tùy tỉ lệ TTFT và TPOT. Người dùng của bạn thích token đầu tiên hiện ngay rồi chờ lâu hơn giữa các token, hay thích chờ lâu hơn một chút ở đầu rồi chữ chạy vèo vèo? Huyen nói phải có nghiên cứu người dùng mới biết — và việc dịch chuyển máy từ decoding sang prefilling (hoặc ngược lại) cho phép đánh đổi giữa hai chỉ số này.1

    Hai tiệm cùng giao hàng trong một tiếng. Tiệm A gọi lại ngay rồi làm chậm; tiệm B im lặng một lúc rồi làm nhanh. Tổng như nhau nhưng cảm giác khác hẳn. Nhớ nhé: cái người ta nhớ không phải tổng thời gian, mà là lúc nào mình bắt đầu thấy có chuyện xảy ra.

    Two applications with the same total latency can offer very different experiences depending on how TTFT and TPOT split. Do your users prefer instant first tokens with a longer wait between tokens, or a slightly longer wait up front with fast generation afterwards? Huyen says user studies are needed to find out — and shifting compute instances from decoding to prefilling (or back) is what lets you trade one for the other.1

    Thấy nó ở đâuWhere you see it Huyen dẫn một mốc cụ thể cho streaming: người đọc rất nhanh cũng chỉ đọc được khoảng 120 ms mỗi token, nên TPOT quanh 120 ms — tức 6–8 token mỗi giây — là đủ cho phần lớn tình huống. Nhanh hơn nữa gần như không ai nhận ra.1 Chữ chạy nhanh hơn mắt đọc thì cũng chẳng để làm gì. Huyen gives a concrete anchor for streaming: a very fast reader reads about 120 ms per token, so a TPOT of around 120 ms — roughly 6–8 tokens per second — is sufficient for most use cases. Faster than that, almost nobody notices.1

    TTFT của mô hình ≠ TTFT của người dùng

    Trong các truy vấn kiểu CoT hay tác tử, mô hình sinh nhiều bước trung gian không hiện ra cho người dùng: nó lập kế hoạch, thực hiện hành động và ghi log, rồi mới sinh câu trả lời cuối. Từ góc nhìn mô hình, token đầu tiên ra ở bước một; từ góc nhìn người dùng, mãi bước ba mới thấy. Một số đội dùng chỉ số time to publish để nói rõ rằng họ đang đo tới token người dùng nhìn thấy.1

    Họ hàng của TPOT

    Cùng đo khoảng cách giữa các token đầu ra còn có time between tokens (TBT) và inter-token latency (ITL). Huyen ghi chú rằng TBT là cách gọi của LinkedIn còn ITL là cách gọi của NVIDIA — một ví dụ nhỏ cho thấy thuật ngữ trong lĩnh vực này vẫn chưa hội tụ.1

  2. 06
    Throughput, cost, and the latency trade-off

    Thông lượng, chi phí, và cái giá phải trảĐông khách thì mỗi khách chờ lâu hơnThroughput, cost, and the trade-off

    Thông lượng gắn thẳng với chi phí tính toán: thông lượng càng cao thì giá mỗi token càng rẻ. Huyen tính mẫu — hệ thống tốn 2 đô/giờ và đạt 100 token/giây thì khoảng 5,556 đô cho mỗi triệu token đầu ra; nếu mỗi yêu cầu sinh trung bình 200 token thì decode 1.000 yêu cầu tốn 1,11 đô. Cộng thêm phần prefill (2 đô/giờ, 100 yêu cầu/phút → 0,33 đô cho 1.000 yêu cầu), tổng là 1,44 đô.1

    Một cái bếp chạy cả giờ tốn ngần ấy tiền. Nấu được càng nhiều món trong giờ đó thì mỗi món càng rẻ. Nhưng nấu nhiều cùng lúc thì mỗi người lại phải chờ lâu hơn một chút. Nhớ nhé: rẻ và nhanh thường kéo nhau về hai phía.

    Throughput is directly linked to compute cost: higher throughput usually means lower cost per token. Huyen works the arithmetic — a system costing $2/h at 100 tokens/s comes to about $5.556 per 1M output tokens; at 200 output tokens per request, decoding 1K requests costs $1.11. Adding prefill ($2/h at 100 requests/minute → $0.33 per 1K requests) gives $1.44 in total.1

    Thấy nó ở đâuWhere you see it Theo đội AI của LinkedIn sau một năm triển khai sản phẩm AI sinh, chuyện tăng gấp đôi hoặc gấp ba thông lượng là không hiếm — nếu bạn chịu hi sinh TTFT và TPOT.5 Đó chính là lý do đừng chọn dịch vụ chỉ bằng thông lượng và giá. Muốn rẻ gấp đôi thì thường phải chấp nhận chờ lâu hơn. According to LinkedIn's AI team reflecting on a year of shipping generative AI products, it is not uncommon to double or triple throughput — if you are willing to sacrifice TTFT and TPOT.5 Which is exactly why you should not pick a service on throughput and price alone.

    So sánh thông lượng là so sánh khập khiễng

    Ngay cả với mô hình, phần cứng và workload tương đương, so thông lượng trực tiếp cũng chỉ gần đúng — vì "token" là gì lại tùy vào bộ tách token, mà mỗi mô hình có bộ tách riêng. Huyen khuyên so sánh hiệu quả của các máy chủ suy luận bằng chỉ số như chi phí mỗi yêu cầu.1

    Vì sao goodput ra đời

    Goodput là chỉ số mượn từ ngành mạng, đếm số yêu cầu mỗi giây thỏa mãn SLO. Giả sử SLO của bạn là TTFT tối đa 200 ms và TPOT tối đa 100 ms: dịch vụ hoàn tất 100 yêu cầu/phút nhưng chỉ 30 đạt chuẩn thì goodput là 30 yêu cầu/phút. Chỉ số này giữ cho việc chạy theo thông lượng không âm thầm phá hỏng trải nghiệm.1

  3. 07
    Utilization, MFU, and MBU

    "GPU utilization" là một cái bẫyMáy bận không có nghĩa là máy giỏi"GPU utilization" is a trap

    Chỉ số GPU utilization mà công cụ nvidia-smi hiển thị chỉ là phần trăm thời gian GPU đang xử lý tác vụ. Huyen chỉ ra chỗ hỏng bằng một ví dụ nhỏ: một GPU làm được 100 phép tính mỗi giây vẫn có thể báo 100% utilization trong khi nó chỉ đang làm đúng một phép tính mỗi giây. Bạn trả tiền cho 100 mà dùng có 1.1

    Một người ngồi ở bàn làm việc suốt tám tiếng chưa chắc đã làm được nhiều việc. Cái ta cần biết không phải "có ngồi không" mà "làm được bao nhiêu". Nhớ nhé: bận rộn không đồng nghĩa với hiệu quả.

    The GPU utilization metric shown by nvidia-smi is merely the percentage of time the GPU is actively processing tasks. Huyen exposes the flaw with a small example: a GPU capable of 100 operations per second can report 100% utilization while performing exactly one operation per second. You are paying for 100 and using 1.1

    Thấy nó ở đâuWhere you see it Ví dụ tính MBU của Huyen: mô hình 7B ở FP16 (2 byte mỗi tham số) đạt 100 token/giây thì băng thông đang dùng là 7B × 2 × 100 = 700 GB/s. Chạy trên A100-80GB với băng thông lý thuyết 2 TB/s, MBU là 700 GB/s ÷ 2 TB/s = 70%.1 Phép tính này cũng cho thấy vì sao lượng tử hóa quan trọng: ít byte mỗi tham số nghĩa là tốn ít băng thông quý giá hơn. Chữ nhẹ hơn thì chuyển qua ống dẫn nhanh hơn — đó là lý do người ta "rút gọn" mô hình. Huyen's MBU worked example: a 7B model in FP16 (two bytes per parameter) at 100 tokens/s uses 7B × 2 × 100 = 700 GB/s of bandwidth. On an A100-80GB with a theoretical 2 TB/s, that is an MBU of 700 GB/s ÷ 2 TB/s = 70%.1 The same arithmetic shows why quantization matters: fewer bytes per parameter means less of that precious bandwidth consumed.

    MFU thực tế thấp đến đâu

    Bảng 9-1 của sách trích từ bài báo PaLM (Chowdhery và cộng sự, 2022): GPT-3 175B trên V100 đạt MFU 21,3%; Gopher 280B trên 4.096 TPU v3 đạt 32,5%; Megatron-Turing NLG 530B trên 2.240 A100 đạt 30,2%; PaLM 540B trên 6.144 TPU v4 đạt 46,2%.6 Với huấn luyện, MFU trên 50% nhìn chung được coi là tốt.1

    Tận dụng cao chưa chắc đã đáng mừng

    Huyen chốt lại rằng mục tiêu không phải là tìm con chip có mức tận dụng cao nhất. Thứ bạn thật sự quan tâm là làm xong việc nhanh hơn và rẻ hơn; một tỉ lệ tận dụng cao chẳng nói lên điều gì nếu cả chi phí lẫn độ trễ đều tăng.1 Workload compute-bound thường có MFU cao và MBU thấp; workload bandwidth-bound thì ngược lại.

  4. 08
    AI accelerators — three numbers that matter

    Ba con số của một con chipChọn máy theo ba con sốThree numbers on a chip spec

    Huyen tóm gọn cả một chương phần cứng vào ba đặc tính quan trọng xuyên suốt mọi tình huống: năng lực tính toán (FLOP/s, phụ thuộc độ chính xác số học), dung lượng và băng thông bộ nhớ, và điện năng tiêu thụ. Và ba câu hỏi khi chọn chip: phần cứng có chạy nổi workload của bạn không, mất bao lâu, và tốn bao nhiêu.1

    Chọn máy cũng như chọn xe tải: chở được bao nhiêu, chạy nhanh cỡ nào, tốn xăng ra sao. Ba câu hỏi ấy là đủ. Nhớ nhé: chọn xe phải hợp với hàng mình chở, chứ không phải cứ xe to là hơn.

    Huyen compresses a whole hardware chapter into three characteristics that matter across use cases: computational capabilities (FLOP/s, which depends on numerical precision), memory size and bandwidth, and power consumption. And three questions when choosing a chip: can the hardware run your workloads, how long does it take, and how much does it cost.1

    Thấy nó ở đâuWhere you see it Quy tắc chọn rất thẳng: workload compute-bound thì tìm chip nhiều FLOP/s; workload memory-bound thì bỏ tiền cho chip băng thông cao và nhiều bộ nhớ hơn.1 Nói cách khác, mục 01 quyết định mục này. Kẹt vì tính nhiều thì mua bếp khỏe; kẹt vì khuân nhiều thì mở rộng đường vào kho. The selection rule is blunt: if your workloads are compute-bound, look for chips with more FLOP/s; if they are memory-bound, spend the money on higher bandwidth and more memory.1 In other words, Part 01 decides this part.

    Ba tầng bộ nhớ

    Một accelerator thường làm việc với ba tầng bộ nhớ: CPU memory (DRAM), băng thông thấp nhất, khoảng 25–50 GB/s; GPU HBM, thường 256 GB/s tới hơn 1,5 TB/s, với GPU tiêu dùng có khoảng 24–80 GB; và GPU on-chip SRAM, tốc độ thường vượt 10 TB/s nhưng dung lượng rất nhỏ, thường từ 40 MB trở xuống.1 Rất nhiều việc tối ưu GPU thực chất là tận dụng cho khéo đúng cái thang bậc này.

    Điện là một nút thắt thật

    Một NVIDIA A100 có 54 tỉ transistor, H100 có 80 tỉ. Một H100 chạy hết công suất suốt một năm tiêu thụ khoảng 7.000 kWh — để so sánh, một hộ gia đình Mỹ trung bình dùng 10.000 kWh mỗi năm.1 Huyen coi điện là nút thắt thật sự của việc mở rộng quy mô tính toán.

Mục 03 · Cấp mô hìnhMục 03 · Sửa chính cái máyPart 03 · Model level

Sửa chính mô hìnhLàm cái máy gọn và nhanh hơnChanging the model itself

Phần lớn mô hình nền tảng hôm nay đi theo kiến trúc transformer và có một thành phần mô hình ngôn ngữ tự hồi quy. Huyen chỉ ra ba đặc điểm khiến suy luận của chúng ngốn tài nguyên: kích thước mô hình, giải mã tự hồi quy, và cơ chế attention — và các kỹ thuật cấp mô hình chính là ba hướng tấn công tương ứng.1

Muốn máy chạy nhanh, cách thứ nhất là sửa chính cái máy: làm nó nhỏ lại, hoặc dạy nó viết nhiều chữ một lúc thay vì từng chữ, hoặc giúp nó bớt phải đọc lại những gì đã đọc.

Most of today's foundation models follow the transformer architecture and contain an autoregressive language model component. Huyen names the three characteristics that make their inference resource-intensive: model size, autoregressive decoding, and the attention mechanism — and the model-level techniques are the three corresponding lines of attack.1

Lý tưởng thì tối ưu tốc độ và chi phí không nên đổi chất lượng mô hình. Nhưng nhiều kỹ thuật vẫn gây suy giảm — đó là lý do cùng một mô hình Llama, các nhà cung cấp khác nhau lại cho kết quả benchmark hơi khác nhau.17

Làm máy nhanh hơn đôi khi khiến nó trả lời kém đi một chút — nên phải kiểm tra lại sau khi tối ưu.

Ideally, optimising for speed and cost should not change model quality. But many techniques do cause degradation — which is why the same Llama model, served by different providers, shows slightly different benchmark results.17

Đây là điểm phân biệt then chốt giữa hai mục cuối của chương: tối ưu cấp mô hình thường phải sửa chính mô hình, nên có thể đổi hành vi của nó; còn tối ưu cấp dịch vụ giữ nguyên mô hình và chỉ đổi cách phục vụ, nên lẽ ra không được làm đổi chất lượng đầu ra.1 Khi mua dịch vụ suy luận, đây là câu hỏi đáng hỏi thẳng nhà cung cấp.

QuantizationGiảm độ chính xác số học để thu nhỏ dấu chân bộ nhớ và tăng thông lượng. Từ 32 bit xuống 16 bit là giảm một nửa bộ nhớ.1Ghi số thô hơn cho nhẹ đi.Reduce numerical precision to shrink the memory footprint and raise throughput. From 32 to 16 bits halves the footprint.1
DistillationHuấn luyện một mô hình nhỏ bắt chước hành vi của mô hình lớn (bàn ở Chương 8).1Dạy học trò nhỏ bắt chước thầy lớn.Train a small model to mimic the behaviour of a large one (covered in Chapter 8).1
PruningHoặc bỏ hẳn các nút của mạng, hoặc đưa những tham số ít hữu ích nhất về 0 để mô hình thưa hơn.1Tỉa bớt những cành không sinh trái.Either remove whole nodes from the network, or set the least useful parameters to zero to make the model sparse.1
Cỡ KV cacheKV cache size2 × B × S × L × H × M — lô, độ dài chuỗi, số lớp, chiều mô hình, số byte mỗi giá trị.1Sổ ghi nhớ càng dài thì càng chiếm chỗ.2 × B × S × L × H × M — batch, sequence length, layers, model dimension, bytes per value.1
  1. 09
    Model compression

    Nén mô hình — và vì sao pruning ít được dùngLàm mô hình nhỏ lạiCompression — and why pruning is rare

    Lượng tử hóa chỉ trọng số là cách phổ biến nhất, theo Huyen, vì dễ dùng, chạy được ngay với nhiều mô hình, và cực kỳ hiệu quả — dù bà nhắc rằng ta đã gần tới giới hạn, không thể xuống dưới 1 bit mỗi giá trị. Chưng cất cũng thường gặp vì cho ra mô hình nhỏ mà hành vi tương đương mô hình lớn hơn nhiều.1

    Muốn cái máy nhẹ đi thì có ba cách: ghi số thô hơn, dạy một học trò nhỏ bắt chước thầy, hoặc tỉa bớt những phần không cần. Cách thứ nhất phổ biến nhất vì dễ làm nhất. Nhớ nhé: nhẹ đi thì nhanh hơn, nhưng đừng nhẹ tới mức quên mất việc.

    Weight-only quantization is by far the most popular approach, Huyen writes, because it is easy to use, works out of the box for many models, and is extremely effective — though she notes we are close to its limit, since you cannot go below 1 bit per value. Distillation is also common, because it yields a small model whose behaviour is comparable to a much larger one for your needs.1

    Thấy nó ở đâuWhere you see it Pruning có kết quả nghiên cứu rất đẹp — Frankle và Carbin (2019) cho thấy có thể giảm hơn 90% số tham số khác 0 của một số mạng đã huấn luyện mà không hại độ chính xác.8 Nhưng trong thực tế nó ít được dùng: khó làm, đòi hiểu kiến trúc gốc, hiệu quả thường kém các cách khác, và mô hình thưa lại không phải kiến trúc phần cứng nào cũng tận dụng được.1 Trong phòng thí nghiệm thì tỉa cành rất hiệu quả; ra đời thật thì ít ai làm vì khó và máy móc không tận dụng được. Pruning has beautiful research results — Frankle and Carbin (2019) showed non-zero parameter counts of certain trained networks can be cut by over 90% without compromising accuracy.8 In practice it is uncommon: it is hard to do, requires understanding the original architecture, the gain is often smaller than other approaches, and not all hardware exploits the resulting sparsity.1

    Hai nghĩa của pruning

    Một là bỏ hẳn các nút của mạng — tức đổi kiến trúc và giảm số tham số. Hai là tìm những tham số ít hữu ích nhất cho dự đoán rồi đặt chúng về 0; cách này không giảm tổng số tham số, chỉ giảm số tham số khác 0, làm mô hình thưa hơn, vừa giảm chỗ lưu vừa tăng tốc tính toán.1

    Pruning như công cụ tìm kiến trúc

    Mô hình đã tỉa có thể dùng luôn hoặc tinh chỉnh tiếp để khôi phục phần chất lượng đã mất. Huyen còn dẫn một hướng khác: pruning giúp phát hiện những kiến trúc triển vọng (Liu và cộng sự, 2018), và các kiến trúc đã tỉa ấy — nhỏ hơn kiến trúc gốc — cũng có thể huấn luyện lại từ đầu.19

  2. 10
    Speculative decoding

    Giải mã suy đoán — để người yếu viết nhápCho người viết nhanh viết nháp trướcSpeculative decoding — let the weak model draft

    Một mô hình nhanh nhưng yếu hơn (draft model) sinh trước một chuỗi K token; mô hình đích xác minh cả K token ấy song song, chấp nhận chuỗi con dài nhất tính từ trái sang mà nó đồng ý, rồi tự sinh thêm một token. Nếu không token nháp nào được nhận, vòng lặp chỉ cho ra một token do mô hình đích sinh; nếu tất cả được nhận, nó cho ra K + 1 token.1

    Giống như có một bạn viết nhanh ngồi viết nháp vài chữ trước, rồi thầy giáo đọc lướt một lượt — chữ nào đúng ý thì giữ, tới chữ đầu tiên sai thì bỏ từ đó về sau. Đọc lướt bao giờ cũng nhanh hơn tự viết. Nhớ nhé: kiểm bài nhanh hơn làm bài.

    A faster but weaker draft model generates a sequence of K tokens; the target model verifies all K in parallel, accepts the longest left-to-right subsequence it agrees with, then generates one extra token itself. If no draft token is accepted, the loop yields only the one token from the target model; if all are accepted, it yields K + 1 tokens.1

    Thấy nó ở đâuWhere you see it Để tăng tốc Chinchilla-70B, DeepMind huấn luyện một mô hình nháp 4B cùng kiến trúc; nó sinh token nhanh gấp tám lần mô hình đích (1,8 ms/token so với 14,1 ms/token), giúp giảm hơn một nửa tổng độ trễ mà không ảnh hưởng chất lượng.10 Kỹ thuật này đã có trong vLLM, TensorRT-LLM và llama.cpp.1 Có nơi đã làm thử: người viết nháp nhanh gấp tám lần, và cả bài xong nhanh hơn gấp đôi. To speed up Chinchilla-70B, DeepMind trained a 4B draft model of the same architecture; it generates a token eight times faster than the target (1.8 ms/token vs 14.1 ms/token), halving overall response latency without compromising quality.10 The technique now ships in vLLM, TensorRT-LLM and llama.cpp.1

    Vì sao nó không phản tác dụng

    Ba nhận xét làm nên kỹ thuật này. Một, xác minh nhanh hơn sinh vì xác minh song song hóa được còn sinh thì tuần tự — nói cách khác, giải mã suy đoán biến hồ sơ tính toán của decode thành hồ sơ của prefill. Hai, trong một chuỗi đầu ra có những token dễ đoán hơn hẳn, nên một mô hình yếu vẫn đạt tỉ lệ chấp nhận cao. Ba, decode vốn bandwidth-bound nên thường còn FLOP nhàn rỗi để xác minh gần như miễn phí.1

    Chọn K thế nào

    Tỉ lệ chấp nhận phụ thuộc lĩnh vực: với văn bản có cấu trúc chặt như mã nguồn, tỉ lệ thường cao hơn. K lớn nghĩa là mô hình đích phải gọi xác minh ít lần hơn, nhưng tỉ lệ chấp nhận lại thấp đi. Mô hình nháp có thể thuộc kiến trúc bất kỳ, song lý tưởng nhất là dùng chung từ vựng và bộ tách token với mô hình đích.1

  3. 11
    Inference with reference & parallel decoding

    Chép lại từ đề bài, và viết nhiều chữ cùng lúcChép lại phần có sẵnCopy from the input, and write several tokens at once

    Inference with reference giống giải mã suy đoán, nhưng token nháp không do mô hình nào sinh ra mà được chọn từ chính đầu vào. Nó không cần mô hình phụ, đổi lại chỉ hữu ích khi đầu ra trùng lặp nhiều với ngữ cảnh — như hệ thống truy xuất, viết mã, hay hội thoại nhiều lượt. Trong bài báo gốc (Yang và cộng sự, 2023), kỹ thuật này đạt tốc độ sinh nhanh gấp hai lần ở những tình huống ấy.11

    Nhiều khi câu trả lời chỉ là chép lại một đoạn trong đề bài — ví dụ khi bạn nhờ sửa lỗi một đoạn mã, phần lớn đoạn mã vẫn giữ nguyên. Vậy thì cứ chép, đừng viết lại từng chữ. Nhớ nhé: cái gì đã có sẵn thì đừng viết lại.

    Inference with reference works like speculative decoding, except the draft tokens are not generated by a model but selected from the input. It needs no extra model, but is useful only where output overlaps heavily with context — retrieval systems, coding, multi-turn conversations. In the original paper (Yang et al., 2023) it achieved a two-times generation speedup in such use cases.11

    Thấy nó ở đâuWhere you see it Giải mã song song đi xa hơn: nó phá luôn sự phụ thuộc tuần tự, sinh xt+1, xt+2… cùng lúc. Nó khả thi vì biết phần đã có thường đủ để đoán vài token kế — ví dụ của Huyen: với "the cat sits", dù chưa biết chữ sau là "on", "under" hay "behind", bạn vẫn đoán được chữ tiếp sau nữa là "the".1 Có những chỗ trong câu đoán trước được, như "con mèo ngồi trên… cái gì đó" — chữ "cái" thì chắc chắn rồi. Parallel decoding goes further, breaking the sequential dependency to generate xt+1, xt+2… simultaneously. It works because the existing sequence is often enough to predict the next few tokens — Huyen's example: given "the cat sits", without knowing whether the next token is "on", "under" or "behind", you can still predict the word after it is "the".1

    Hai kiểu giải mã song song

    Token song song có thể do cùng một bộ giải mã sinh ra, như trong Lookahead decoding (Fu và cộng sự, 2024), hoặc do nhiều đầu giải mã khác nhau, như trong Medusa (Cai và cộng sự, 2024). Trong Medusa, mô hình gốc được gắn thêm nhiều đầu giải mã; mỗi đầu là một lớp mạng nhỏ được huấn luyện để dự đoán một token ở vị trí tương lai cụ thể, huấn luyện cùng mô hình gốc nhưng mô hình gốc bị đóng băng.12

    Xác minh và cái giá của sự phức tạp

    Vì không sinh tuần tự, các token phải được xác minh xem có khớp với nhau không. Lookahead dùng phương pháp Jacobi — nên họ thuật toán này còn gọi là Jacobi decoding; Medusa dùng attention dạng cây để chọn tổ hợp triển vọng nhất. NVIDIA công bố Medusa giúp tăng tốc sinh token của Llama 3.1 tới 1,9 lần trên GPU HGX H200 của họ.13 Huyen thừa nhận thẳng: giải mã song song không trực giác, và vài kỹ thuật như Medusa khá khó cài đặt.1

  4. 12
    KV cache and attention optimization

    KV cache — cuốn sổ ngày càng dàyCuốn sổ ghi nhớThe KV cache — a notebook that keeps growing

    Để sinh token kế tiếp, mô hình cần vector key và value của mọi token trước đó. Thay vì tính lại từ đầu mỗi bước, nó lưu chúng vào KV cache và chỉ tính vector cho token mới nhất.1 Cái giá: cache phình theo độ dài chuỗi và theo cỡ lô. Một bài báo của Google tính rằng với mô hình hơn 500B dùng multi-head attention, batch 512, ngữ cảnh 2.048, KV cache lên tới 3 TB — gấp ba lần trọng số của chính mô hình đó.14

    Mỗi khi viết thêm một chữ, máy phải nhớ lại tất cả những chữ đã viết. Để khỏi đọc lại từ đầu, nó ghi sẵn vào một cuốn sổ. Nhưng cuốn sổ ấy càng viết càng dày, tới lúc không còn chỗ để nữa. Nhớ nhé: ghi sổ giúp nhanh hơn, nhưng sổ cũng chiếm chỗ.

    To generate the next token, the model needs the key and value vectors of every previous token. Rather than recompute them each step, it stores them in a KV cache and computes vectors only for the newest token.1 The price: the cache grows with sequence length and with batch size. A Google paper calculated that for a 500B+ model with multi-head attention, batch size 512 and context length 2,048, the KV cache totals 3 TB — three times the size of that model's weights.14

    Thấy nó ở đâuWhere you see it Character.AI cho biết hội thoại trung bình của họ có lịch sử 180 tin nhắn, nên nút thắt chính của thông lượng suy luận là cỡ KV cache. Ba thiết kế attention — multi-query attention, xen kẽ local và global attention, và cross-layer attention — giúp họ giảm KV cache hơn 20 lần, tới mức bộ nhớ không còn là nút thắt khi phục vụ lô lớn.15 Có công ty chat với người dùng suốt, sổ dày kinh khủng; họ tìm cách ghi gọn lại hơn hai mươi lần. Character.AI reports an average conversation history of 180 messages, making KV cache size their primary inference-throughput bottleneck. Three attention designs — multi-query attention, interleaved local and global attention, and cross-layer attention — cut their KV cache by over 20 times, to the point where memory is no longer the bottleneck for large batch sizes.15

    Ba hướng tối ưu attention

    Huyen chia chúng thành ba nhóm. Thiết kế lại cơ chế attention — local windowed attention, cross-layer attention, multi-query attention, grouped-query attention; vì đổi kiến trúc nên chỉ áp dụng được khi huấn luyện hoặc tinh chỉnh. Tối ưu KV cache — như PagedAttention của vLLM, chia cache thành các khối không liền kề để giảm phân mảnh và cho phép chia sẻ bộ nhớ linh hoạt. Viết kernel — như FlashAttention, hợp nhất nhiều toán tử thường dùng trong transformer thành một.11617

    Tính thử cỡ cache

    Công thức là 2 × B × S × L × H × M. Ví dụ của sách: Llama 2 13B có 40 lớp và chiều mô hình 5.120; với batch 32, chuỗi 2.048 và 2 byte mỗi giá trị, KV cache cần 2 × 32 × 2.048 × 40 × 5.120 × 2 = 54 GB nếu không tối ưu gì.1 Lưu ý rằng KV cache chỉ dùng khi suy luận, không dùng khi huấn luyện — lúc huấn luyện mọi token đã biết trước nên tính được một lần.

Mục 04 · Cấp dịch vụMục 04 · Sắp xếp lại hàng đợiPart 04 · Service level

Sắp xếp lại cách phục vụSắp lại hàng cho khéoRearranging how you serve

Phần lớn kỹ thuật cấp dịch vụ xoay quanh quản lý tài nguyên: cho trước một lượng tính toán và bộ nhớ cố định cùng khối lượng công việc biến động, làm sao cấp phát hiệu quả để tối ưu độ trễ và chi phí. Khác với nhóm cấp mô hình, chúng không sửa mô hình và lẽ ra không đổi chất lượng đầu ra.1

Phần này không động vào cái máy nữa. Nó chỉ lo sắp xếp: ai vào trước, ai đi chung chuyến, cái gì đã làm rồi thì để dành dùng lại.

Most service-level techniques are about resource management: given a fixed amount of compute and memory and dynamic workloads, how do you allocate efficiently to optimise latency and cost. Unlike the model-level family, they do not modify models and should not change output quality.1

Xử lý từng yêu cầu riêng lẻ giống như ai nấy lái xe riêng; gộp lô là cho tất cả lên một chuyến xe buýt. Xe buýt chở được nhiều người hơn, nhưng cũng làm chuyến đi của mỗi người dài ra một chút.1

Đi chung xe buýt thì chở được nhiều người hơn, nhưng mỗi người phải chờ thêm chút ít.

Processing each request separately is like everyone driving their own car; batching is putting them all on a bus. A bus moves more people, but it also makes each person's journey a bit longer.1

Huyen theo ẩn dụ xe buýt suốt cả ba kiểu gộp lô, và nó rất đắt. Static batching là chiếc xe chờ đầy ghế mới chạy — yêu cầu đầu tiên phải chờ yêu cầu cuối cùng, dù nó tới muộn cỡ nào. Dynamic batching là xe chạy theo giờ cố định hoặc khi đã đầy, tùy cái nào tới trước — giữ độ trễ trong tầm kiểm soát, đổi lại lô có thể chưa đầy nên phí chỗ. Continuous batching là xe vừa trả một khách xuống là đón ngay khách mới lên, giữ tỉ lệ lấp đầy cao nhất.1

Static batchingGộp một số lượng đầu vào cố định; cả lô phải chờ đủ mới chạy.1Xe chờ đủ khách mới lăn bánh.Group a fixed number of inputs; the whole batch waits until it is full.1
Dynamic batchingĐặt cửa sổ thời gian tối đa: batch 4, cửa sổ 100 ms thì chạy khi đủ 4 yêu cầu hoặc khi hết 100 ms, tùy cái nào trước.1Xe chạy theo giờ, đủ khách hay chưa cũng đi.Set a maximum time window: with batch size 4 and a 100 ms window, run when four requests arrive or when 100 ms passes, whichever comes first.1
Continuous batchingTrả từng câu trả lời ngay khi nó xong và nhận yêu cầu mới vào chỗ trống; còn gọi là in-flight batching.1Trả khách xuống là đón ngay khách mới.Return each response as soon as it completes and slot a new request into its place; also called in-flight batching.1
Tensor parallelismChia các tensor trong một toán tử ra nhiều thiết bị — cách chia mô hình phổ biến nhất khi suy luận.1Chia một phép tính lớn cho nhiều máy cùng làm.Partition the tensors inside an operator across devices — the most common way to split a model for inference.1
Replica parallelismTạo nhiều bản sao của cùng một mô hình để nhận nhiều yêu cầu cùng lúc; dễ triển khai nhất.1Mở thêm quầy giống hệt quầy cũ.Create multiple replicas of the model to handle more concurrent requests; the easiest strategy to implement.1
  1. 13
    Continuous batching

    Đừng bắt câu ngắn chờ câu dàiAi xong trước thì về trướcDon't make short answers wait for long ones

    Trong cách gộp lô ngây thơ, cả lô phải xong hết mới trả về. Với LLM điều này rất tai hại: nếu một yêu cầu sinh 10 token còn yêu cầu khác sinh 1.000 token thì câu ngắn phải chờ câu dài, tạo ra độ trễ hoàn toàn không cần thiết. Continuous batching, giới thiệu trong bài báo Orca (Yu và cộng sự, 2022), cho phép trả câu trả lời ngay khi nó xong và nhận yêu cầu mới vào chỗ vừa trống.19

    Tưởng tượng cả lớp làm bài, ai xong trước vẫn phải ngồi chờ bạn chậm nhất mới được nộp — vô lý quá. Cách hay hơn: ai xong thì nộp và ra về, chỗ trống có bạn mới vào ngồi ngay. Nhớ nhé: đừng bắt người nhanh chờ người chậm.

    In naive batching, the whole batch must complete before any response is returned. For LLMs that is costly: if one request generates 10 tokens and another generates 1,000, the short response waits for the long one, creating entirely unnecessary latency. Continuous batching, introduced in the Orca paper (Yu et al., 2022), returns each response as soon as it completes and admits a new request into the freed slot.19

    Thấy nó ở đâuWhere you see it Đây là lý do các framework phục vụ LLM hiện đại đều quảng cáo continuous hoặc in-flight batching như tính năng hàng đầu. Nếu bạn đánh giá một dịch vụ suy luận, đây là câu hỏi đáng hỏi trước cả khi hỏi về phần cứng. Phần mềm phục vụ hiện đại nào cũng làm được điều này — nên cứ hỏi cho chắc. This is why every modern LLM serving framework advertises continuous or in-flight batching as a headline feature. If you are evaluating an inference service, ask about this before you ask about hardware.

    Nó hoạt động bằng cách nào

    Continuous batching gộp lô một cách chọn lọc: chỉ gộp những thao tác mà việc sinh câu trả lời này không giữ chân câu trả lời kia. Sau khi một yêu cầu trong lô xong và được trả về, dịch vụ đưa một yêu cầu khác vào đúng chỗ đó, khiến việc gộp lô diễn ra liên tục.1

    Đánh đổi của dynamic batching

    Dynamic batching giữ độ trễ trong tầm kiểm soát vì yêu cầu tới sớm không bị yêu cầu tới muộn giam lại. Nhược điểm: lô có thể chưa đầy khi tới hạn xử lý, nên phí một phần năng lực tính toán.1 Đó chính là hình minh họa 9-15 trong sách — gộp lô động dễ chịu về độ trễ nhưng kém hiệu quả về tính toán.

  2. 14
    Decoupling prefill and decode

    Tách prefill khỏi decodeTách bếp đọc đề và bếp viết bàiDecoupling prefill and decode

    Vì prefill compute-bound còn decode bandwidth-bound, để cả hai trên cùng một máy khiến chúng tranh tài nguyên và làm xấu cả TTFT lẫn TPOT. Huyen mô tả rất cụ thể: một GPU đang chạy gần hết công suất có thể nhận thêm một việc nhẹ như decode, nhưng thêm một truy vấn mới nghĩa là thêm cả một việc prefill — và việc prefill ấy sẽ rút cạn tài nguyên tính toán của các việc decode đang chạy, làm chậm TPOT của chúng.1

    Trong bếp có hai việc: đọc đơn hàng và nấu món. Đọc đơn rất nặng đầu, nấu món thì nặng tay. Bắt một người làm cả hai thì việc nào cũng chậm. Tách ra hai người thì trôi hẳn. Nhớ nhé: hai việc khác tính chất thì đừng dồn cho một chỗ.

    Because prefill is compute-bound and decode is memory bandwidth-bound, running both on the same machine makes them compete for resources and degrades both TTFT and TPOT. Huyen is concrete: a GPU already near peak capacity might absorb another light decoding job, but adding a new query means adding a prefilling job too — and that one prefilling job drains compute from the existing decoding jobs, slowing their TPOT.1

    Thấy nó ở đâuWhere you see it Tỉ lệ máy prefill trên máy decode phụ thuộc workload và ưu tiên. Huyen đưa hai khoảng tham khảo: nếu chuỗi đầu vào thường dài và bạn ưu tiên TTFT, tỉ lệ có thể nằm giữa 2:1 và 4:1; nếu đầu vào ngắn và bạn ưu tiên TPOT, tỉ lệ có thể là 1:2 tới 1:1.1 Đề dài thì cần nhiều người đọc đề; đề ngắn mà bài dài thì cần nhiều người viết. The ratio of prefill to decode instances depends on workload and priority. Huyen gives two reference ranges: if input sequences are long and you prioritise TTFT, the ratio can be 2:1 to 4:1; if inputs are short and you prioritise TPOT, it can be 1:2 to 1:1.1

    Bằng chứng từ nghiên cứu

    “DistServe” (Zhong và cộng sự, 2024) và “Inference Without Interference” (Hu và cộng sự, 2024) cho thấy với nhiều LLM và ứng dụng phổ biến, giao prefill và decode cho các instance khác nhau — ví dụ các GPU khác nhau — cải thiện đáng kể lượng yêu cầu xử lý được trong khi vẫn giữ ràng buộc độ trễ.2021

    Chi phí truyền trạng thái

    Tách hai pha nghĩa là phải chuyển trạng thái trung gian từ instance prefill sang instance decode. Điểm đáng chú ý là bài báo cho thấy chi phí truyền thông này không lớn trong các cụm GPU hiện đại có kết nối băng thông cao như NVLink trong cùng một node.120

  3. 15
    Prompt caching

    Cache prompt — đừng đọc lại thứ đã đọcĐọc một lần rồi để dànhPrompt caching — stop re-reading the same text

    Nhiều prompt trong một ứng dụng có những đoạn trùng nhau — điển hình nhất là system prompt. Không có cache thì mô hình phải xử lý lại đoạn ấy với từng truy vấn; có cache thì nó chỉ xử lý một lần cho truy vấn đầu tiên. Huyen đưa một phép nhân rất thuyết phục: nếu system prompt của bạn dài 1.000 token và ứng dụng gọi API một triệu lần mỗi ngày, cache prompt giúp bạn khỏi phải xử lý khoảng một tỉ token đầu vào lặp lại mỗi ngày.1

    Mỗi lần bạn hỏi, máy lại phải đọc lại từ đầu bản nội quy dài dằng dặc rồi mới trả lời. Cache giống như bảo nó: đọc một lần thôi, nhớ lấy, lần sau khỏi đọc lại. Nhớ nhé: thứ gì lặp lại y hệt thì làm một lần là đủ.

    Many prompts in an application share overlapping segments — most typically the system prompt. Without a cache the model reprocesses it on every query; with a cache it is processed once, for the first query. Huyen's arithmetic is persuasive: if your system prompt is 1,000 tokens and your application makes one million API calls a day, a prompt cache saves you from processing roughly one billion repetitive input tokens daily.1

    Thấy nó ở đâuWhere you see it Bảng 9-3 của sách, lấy số từ Anthropic (2024): chat với một cuốn sách (prompt 100.000 token được cache) giảm TTFT từ 11,5 giây xuống 2,4 giây (−79%) và giảm 90% chi phí; prompt nhiều ví dụ (10.000 token) từ 1,6 xuống 1,1 giây (−31%) và giảm 86% chi phí; hội thoại 10 lượt với system prompt dài từ khoảng 10 giây xuống khoảng 2,5 giây (−75%) và giảm 53% chi phí.22 Có nơi đo được: hỏi về một cuốn sách dài, nhờ cache mà chờ từ 11 giây rút còn hơn 2 giây. Table 9-3 of the book, with figures from Anthropic (2024): chatting with a book (100,000-token cached prompt) cuts TTFT from 11.5 s to 2.4 s (−79%) and cost by 90%; many-shot prompting (10,000-token prompt) from 1.6 s to 1.1 s (−31%) and cost by 86%; a 10-turn conversation with a long system prompt from ~10 s to ~2.5 s (−75%) and cost by 53%.22

    Không miễn phí

    Giống KV cache, cache prompt có thể rất lớn và chiếm bộ nhớ. Tại thời điểm sách viết, Google Gemini tính token đầu vào đã cache rẻ hơn 75% so với token đầu vào thường, nhưng bạn phải trả thêm phí lưu cache — sách ghi mức 1,00 đô cho mỗi triệu token mỗi giờ.123 Nếu không dùng API có sẵn tính năng này, tự cài đặt đòi khá nhiều công sức kỹ thuật.

    Còn gọi là gì

    Cache prompt còn có tên context cache hoặc prefix cache. Nó đặc biệt hữu ích với các truy vấn quanh cùng một tài liệu dài — một cuốn sách, một codebase — và với hội thoại dài, khi phần xử lý các tin nhắn trước được dùng lại cho tin nhắn sau. Kể từ khi Gim và cộng sự giới thiệu vào tháng 11 năm 2023, nó được đưa vào các model API rất nhanh.124

  4. 16
    Parallelism strategies

    Song song hóa — chia việc hay chia mô hìnhNhiều máy cùng làmParallelism — split the work or split the model

    Đơn giản nhất là replica parallelism: tạo nhiều bản sao của mô hình để nhận nhiều yêu cầu cùng lúc, đổi lại tốn nhiều chip hơn. Khi mô hình lớn tới mức không vừa một máy, ta cần model parallelism — chia chính mô hình ra nhiều máy. Cách chia phổ biến nhất khi suy luận là tensor parallelism: phân mảnh các tensor trong một toán tử ra nhiều thiết bị, ví dụ chia một ma trận theo cột khi nhân hai ma trận.1

    Hai cách chia việc. Một là mở thêm quầy y hệt quầy cũ, ai tới thì vào quầy nào cũng được. Hai là khi cái máy to quá không nhét vừa một phòng, ta chia nó ra nhiều phòng, mỗi phòng giữ một phần. Nhớ nhé: đông khách thì thêm quầy, máy to quá thì chia máy.

    The simplest is replica parallelism: create multiple copies of the model to handle more concurrent requests, at the cost of more chips. When a model is too big for one machine, you need model parallelism — splitting the model across machines. The most common split for inference is tensor parallelism: partitioning the tensors inside an operator across devices, for example splitting one matrix columnwise in a matrix multiplication.1

    Thấy nó ở đâuWhere you see it Tensor parallelism cho hai lợi ích: phục vụ được mô hình lớn không vừa một máy, và giảm độ trễ — dù lợi ích thứ hai có thể bị bào mòn bởi chi phí truyền thông thêm. Ngược lại, pipeline parallelism làm tăng tổng độ trễ mỗi yêu cầu, nên với ứng dụng khắt khe về độ trễ, người ta thường tránh nó và chọn replica parallelism.1 Chia máy ra nhiều phòng thì chạy được máy to, nhưng đi lại giữa các phòng cũng mất thời gian. Tensor parallelism gives two benefits: it lets you serve models that do not fit on one machine, and it reduces latency — though extra communication overhead can eat into the second. Pipeline parallelism, by contrast, increases total per-request latency, so latency-sensitive applications typically avoid it in favour of replica parallelism.1

    Bài toán xếp thùng

    Nhét mô hình đủ cỡ vào chip đủ cỡ là một bài toán bin-packing. Ví dụ của Huyen: với hỗn hợp mô hình 8B, 13B, 34B, 70B và GPU 24 GB, 40 GB, 48 GB, 80 GB, nếu số chip cố định bạn phải quyết định tạo bao nhiêu bản sao cho mỗi mô hình và đặt bản nào lên GPU nào — có nên đặt ba mô hình 13B lên một GPU 40 GB, hay để dành GPU ấy cho một mô hình 34B?1

    Hai kiểu song song cho chuỗi dài

    Hai kỹ thuật ít gặp hơn nhưng đáng biết. Context parallelism: chính chuỗi đầu vào được chia ra các thiết bị, ví dụ nửa đầu xử lý trên máy 1, nửa sau trên máy 2. Sequence parallelism: các toán tử cần cho toàn bộ đầu vào được chia ra các máy — ví dụ attention chạy trên máy 1 còn feedforward chạy trên máy 2.1

Ba hiểu lầm hay gặp

Three common misconceptions

Chương này dễ bị đọc sai theo ba hướng. Mỗi hướng đều dẫn tới một quyết định kỹ thuật tốn kém.

This chapter is easy to misread in three directions. Each one leads to an expensive engineering decision.

"Mua chip mạnh hơn là xong"

"Just buy a faster chip"

Chip nhiều FLOP/s chỉ cứu được workload compute-bound. Suy luận mô hình ngôn ngữ tự hồi quy chủ yếu bandwidth-bound, nên tiền nên đi vào băng thông và vào việc giảm số byte phải chuyển — tức lượng tử hóa và quản lý KV cache.1

More FLOP/s only rescues compute-bound workloads. Autoregressive LLM inference is mostly bandwidth-bound, so the money belongs in bandwidth and in reducing the bytes that must move — quantization and KV cache management.1

"GPU utilization 100% là tối ưu tốt"

"100% GPU utilization means we're optimised"

Chỉ số của nvidia-smi chỉ đếm thời gian GPU đang bận, không đếm lượng việc nó làm. Con chip làm được 100 phép tính mỗi giây vẫn báo 100% khi chỉ làm một phép tính mỗi giây. MFU và MBU mới là chỉ số nói thật.1

The nvidia-smi metric counts the time a GPU is busy, not the work it does. A chip capable of 100 operations per second still reports 100% while doing one. MFU and MBU are the honest metrics.1

"Nhanh hơn thì luôn tốt hơn"

"Faster is always better"

Tối ưu là chuỗi đánh đổi. Tăng thông lượng thường hy sinh độ trễ; nhiều kỹ thuật cấp mô hình có thể làm chất lượng suy giảm. Đó là lý do goodput — số yêu cầu đạt SLO — hữu ích hơn thông lượng trần trụi.15

Optimization is a chain of trade-offs. Raising throughput usually costs latency; many model-level techniques can degrade quality. That is why goodput — requests that meet the SLO — is more useful than raw throughput.15

Tự kiểmTự hỏi mìnhSelf-diagnostic

Hệ thống của bạn đang kẹt ở đâu?Máy của bạn chậm vì đâu?Where is your system stuck?

Sáu câu hỏi theo đúng mạch chương: tìm nút thắt, đo cho đúng, rồi mới chọn thuốc. Trả lời được cả sáu là bạn đã có một bản đồ tối ưu cho hệ thống của mình.

Sáu câu hỏi giúp bạn tìm xem máy của mình đang kẹt chỗ nào.

Six questions following the chapter's own arc: find the bottleneck, measure it properly, then pick the medicine. Answer all six and you have an optimization map for your own system.

Workload của bạn compute-bound hay memory bandwidth-bound? Nếu chưa trả lời được thì mọi quyết định mua phần cứng đều là đoán mò. Công cụ đo như NVIDIA Nsight vẽ biểu đồ roofline đúng để trả lời câu này.2 Nhớ rằng prefill và decode cho ra hai câu trả lời khác nhau trong cùng một lần suy luận — nên câu hỏi đúng phải là "kẹt ở pha nào".
Bạn đang theo dõi TTFT và TPOT riêng, hay chỉ có một con số "độ trễ"? Tổng độ trễ = TTFT + TPOT × số token đầu ra; hai ứng dụng cùng tổng vẫn cho trải nghiệm rất khác. Và với ứng dụng kiểu tác tử, TTFT mà mô hình thấy không phải TTFT mà người dùng thấy — cân nhắc đo thêm "time to publish".
Bạn nhìn trung bình hay nhìn phân vị? Một yêu cầu 3.000 ms lẫn vào chín yêu cầu quanh 100 ms đủ để kéo trung bình lên 390 ms.1 Theo dõi p50, p90, p95, p99, và vẽ TTFT theo độ dài đầu vào để thấy đâu là ngoại lệ thật, đâu là quy luật.
Bạn đã tính goodput chưa, hay mới chỉ tính throughput? Nếu chưa định nghĩa SLO thì không thể tính goodput — mà không có goodput thì rất dễ tối ưu thông lượng tới mức phá hỏng trải nghiệm. LinkedIn ghi nhận có thể tăng gấp đôi, gấp ba thông lượng nếu chịu hy sinh TTFT và TPOT.5
Prompt của bạn có bao nhiêu phần lặp lại giữa các truy vấn? System prompt dài và tài liệu dùng chung là ứng viên số một cho cache prompt. Làm phép nhân của Huyen cho chính hệ thống của bạn: độ dài phần lặp × số lượt gọi mỗi ngày — con số ấy thường lớn tới mức gây sốc.1
Dịch vụ suy luận bạn đang dùng có gộp lô liên tục và tách prefill/decode không? Đây là hai câu hỏi nên hỏi nhà cung cấp trước khi bàn tới phần cứng. Và hỏi thêm câu thứ ba: họ dùng kỹ thuật tối ưu nào có thể làm đổi hành vi mô hình — vì cùng một mô hình Llama qua các nhà cung cấp khác nhau cho điểm benchmark khác nhau.7
Máy của bạn chậm vì phải tính nhiều, hay vì phải khuân nhiều? Hai lý do khác nhau cần hai cách chữa khác nhau.
Bạn có đo riêng "chờ chữ đầu" và "tốc độ viết tiếp" không? Hai thứ này cho cảm giác rất khác nhau, dù cộng lại có thể bằng nhau.
Bạn có đang bị con số trung bình đánh lừa không? Một người phải chờ cực lâu sẽ bị trung bình che mất.
Bạn đếm số khách được phục vụ, hay số khách được phục vụ đúng hẹn? Chỉ con số thứ hai mới nói lên chất lượng dịch vụ.
Có đoạn nào máy phải đọc đi đọc lại mỗi lần không? Nếu có, hãy để dành nó lại — đọc một lần là đủ.
Người nhanh có đang phải chờ người chậm không? Nếu có, hãy để ai xong trước thì về trước.
Is your workload compute-bound or memory bandwidth-bound? Until you can answer this, every hardware purchase is guesswork. Profiling tools like NVIDIA Nsight draw a roofline chart precisely to answer it.2
Do you track TTFT and TPOT separately, or just one "latency" number? Total latency = TTFT + TPOT × output tokens; two apps with the same total can feel entirely different.
Are you looking at averages or percentiles? One 3,000 ms request among nine around 100 ms is enough to drag the average to 390 ms.1
Have you computed goodput, or only throughput? Without a defined SLO there is no goodput — and without goodput it is easy to optimise throughput straight through your user experience.5
How much of your prompt repeats across queries? Long system prompts and shared documents are the prime candidates for a prompt cache. Run Huyen's multiplication on your own traffic.1
Does your inference service do continuous batching and prefill/decode decoupling? Ask these two before discussing hardware — and a third: which optimizations do they use that could change model behaviour?7
Đọng lạiĐọng lạiThe distillation
Tối ưu là tìm đúng nút thắt rồi gỡ đúng nó. Đo trước, chữa sau — vì một cỗ máy bận rộn chưa chắc đã là một cỗ máy hữu ích. Muốn nhanh hơn thì phải biết mình đang kẹt ở đâu. Đo trước, sửa sau — vì bận rộn không có nghĩa là làm được việc. Optimization is finding the right bottleneck and removing that one. Measure first, treat second — because a busy machine is not necessarily a useful one.