前面四篇,我们已经一路走过了:
GPU ↓ CUDA ↓ PyTorch ↓ Tensor上一篇,我们第一次真正让 PyTorch 的 Tensor 进入 GPU。
从:
System RAM经过:
PCIe进入:
GPU VRAM然后执行矩阵计算。
到这里,整个:
Python ↓ PyTorch ↓ CUDA ↓ GPU已经真正跑通了。
但问题也随之而来。
我们现在运行的依然只是:
c = a @ b这种人为制造出来的矩阵计算。
真正的 AI 模型显然不会只有两个 Tensor。
一个大语言模型中还有:
Embedding Attention MLP Normalization Transformer Block以及数量巨大的:
Parameter Weight于是下一步的问题自然变成了:
一个所谓的 LLM,到底是什么?
为什么我们经常看到:
0.5B 1.5B 7B 14B 70B这些数字?
所谓:
7B Model真的就是有 70 亿个数字吗?
这些 Parameter 和 Weight 到底是什么?
为什么一个模型下载下来可能就是几 GB、几十 GB?
为什么:
model.to("cuda")执行以后,GPU 显存会突然增加一大块?
还有我们每天使用大模型时经常碰到的:
Prompt Token Tokenizer Context Transformer又分别是什么?
这一篇,我们暂时不研究:
Prefill Decode KV Cache TTFT TPOT这些属于“模型已经加载之后,一次请求到底怎么运行”的问题。
这一篇只回答一个更基础的问题:
从 AI Infra 的角度,一个 LLM 本身究竟是什么?
一、一个 LLM,并不是一个巨大的“程序”
第一次接触大模型时,我很容易把:
Qwen Llama DeepSeek理解成某种特别大的软件。
好像我们平时安装:
Chrome Nginx MySQL一样。
下载一个模型,然后运行它。
但从 Infra 角度来看,一个已经训练好的 LLM 更接近:
模型架构 + 模型参数 + Tokenizer + 配置文件如果去看一个 Hugging Face 模型目录,经常会看到类似:
config.json model.safetensors tokenizer.json tokenizer_config.json generation_config.json ...这些文件扮演的角色并不一样。
例如:
config.json主要描述模型结构。
里面可能包含:
Hidden Size Transformer Layers Attention Heads Vocabulary Size Context Length ...而:
tokenizer.json描述的是:
文字 ↓ Token应该怎样转换。
真正最占空间的,通常是:
model.safetensors或者被拆成多个:
model-00001-of-000xx.safetensors这样的文件。
因为这里面保存的是训练结束以后得到的大量:
Model Weights也就是模型权重。
所以可以先建立一个非常粗略,但对 Infra 很有用的理解:
LLM │ ├── Architecture │ ├── Parameters / Weights │ ├── Tokenizer │ └── Config而真正吃:
Disk RAM VRAM的主要就是其中那一大堆:
Parameters / Weights二、0.5B、7B、70B,B 到底是什么意思?
我们经常看到模型名字里写:
0.5B 1.5B 7B 14B 32B 70B这里的:
B就是:
Billion十亿。
所以:
0.5B ≈ 5 亿参数 7B ≈ 70 亿参数 70B ≈ 700 亿参数这里所谓的:
Parameter就是:
模型训练过程中学习出来,并在训练结束以后保存下来的参数。
假设一个非常简单的神经网络层:
torch.nn.Linear(1024, 4096)它内部就会包含一组巨大的:
Weight Tensor以及可能存在的:
Bias Tensor而真正的大语言模型中,会有很多层:
Embedding ↓ Transformer Block ↓ Transformer Block ↓ Transformer Block ↓ ... ↓ Output Layer每一层里面又包含大量:
Weight最终把整个模型中的参数全部加起来,就可能变成:
5 亿 70 亿 700 亿甚至更多。
所以:
7B Model最直接的含义并不是:
这个模型文件有 7GB。
而是:
这个模型大约拥有 70 亿个 Parameter。
三、Parameter 和 Weight 有什么区别?
这两个词在 AI 文章里经常混着出现。
严格来说:
Parameter范围更大。
模型里面需要训练和保存的:
Weight Bias ...都可能属于 Parameter。
而:
Weight通常更具体地指:
某一层中的权重矩阵例如一个 Linear Layer 里面的:
Weight Tensor不过到了大模型领域,我们经常会听到:
下载模型权重 加载模型权重 权重占多少显存 Model Weights这里的:
Weights通常已经被比较宽泛地用来表示:
模型训练以后保存下来的那些参数数据。
所以从 Infra 角度,目前不用过度纠结两者的边界。
先理解成:
Model │ ├── Parameter │ ├── Weight Tensor │ ├── Bias Tensor │ └── ... │ ├── Parameter │ └── ...就够了。
更重要的是:
这些 Parameter 最终仍然是我们上一篇已经认识过的 Tensor。
只不过现在不是:
1 个 Tensor而是:
成千上万个 Tensor + 几亿甚至几十亿个元素共同组成了一个模型。
四、前几篇的 Tensor,终于和 Model 接起来了
上一篇我们已经知道,一个 Tensor 最值得关注的几个属性包括:
shape dtype device现在到了 Model,这些知识仍然有效。
模型参数本身也是 Tensor。
所以一个模型里的某个 Weight 可能是:
shape = [4096, 4096] dtype = float16 device = cpu当模型进入 GPU 后则变成:
device = cuda:0于是前几篇一路留下来的几个概念终于接起来:
Tensor ↓ Parameter ↓ Model ↓ GPU VRAM这也是我觉得学习 AI Infra 时很重要的一点。
如果直接从:
AutoModelForCausalLM.from_pretrained(...)开始,很容易觉得:
Model是一个巨大的黑盒。
但拆开以后会发现:
所谓模型,本质上还是数量巨大的 Tensor 被按照某种网络结构组织起来。
五、为什么参数数量会直接影响模型大小?
现在可以做一个非常简单的估算。
假设模型有:
0.5B Parameters也就是大约:
5 × 10^8个参数。
如果每个参数使用:
FP16上一篇已经知道:
FP16 = 2 Bytes那么只算模型参数:
0.5 × 10^9 × 2 Bytes ≈ 1GB如果换成:
7B FP16就是:
7 × 10^9 × 2 Bytes ≈ 14GB现在第二篇里我们曾经提前做过的:
7B × 2 Bytes ≈ 14GB终于不再只是一个公式。
因为现在知道:
7B代表:
70 亿个 Parameter而:
2 Bytes来自:
Parameter Tensor 的 dtype于是关系真正变成:
Parameter Count × Parameter dtype ↓ Weight Size ↓ RAM / VRAM这是一条非常重要的 AI Infra 关系。
六、模型文件大小为什么和显存占用有关?
现在再去看:
model.safetensors就容易理解了。
里面主要保存的是:
训练完成后的 Parameter Tensor所以如果一个模型大约:
0.5B Parameters并且权重以:
FP16 / BF16保存,那么模型权重文件大约在:
1GB这个量级并不奇怪。
但这里要特别注意:
模型文件大小和:
模型运行时 GPU 显存占用并不一定完全相等。
因为模型真正运行以后,显存里以后还会出现其他数据。
这一篇我们暂时只知道:
VRAM │ ├── Model Weights │ └── Runtime Data其中:
Model Weights比较像:
模型加载以后长期驻留 GPU 的静态资源。
至于 Runtime Data 到底有哪些、为什么会随着 Prompt 和请求数量变化,我们留到下一篇再展开。
这一篇只需要先记住:
模型权重通常是 LLM 显存中最大、最基础的一块长期资源。
七、Transformer 又是什么?
讲 LLM 绕不开:
Transformer但这一篇我们不准备推导:
Q K V Softmax Attention Formula这些数学。
对于 AI Infra 来说,现在只需要知道它处在哪一层。
今天绝大多数主流 LLM,核心都建立在 Transformer 架构之上。
一个 Decoder-only LLM 可以非常粗略地理解成:
Input ↓ Embedding ↓ ┌──────────────────────┐ │ Transformer Block │ │ │ │ Attention │ │ MLP │ │ Normalization │ └──────────────────────┘ ↓ ┌──────────────────────┐ │ Transformer Block │ └──────────────────────┘ ↓ ... ↓ ┌──────────────────────┐ │ Transformer Block │ └──────────────────────┘ ↓ Output关键是:
Transformer Block并不是程序里一段没有数据的逻辑。
里面存在大量:
Weight Tensor于是:
Transformer Layer 越多 Hidden Size 越大 各种矩阵越大通常也就意味着:
Parameter 更多最终:
Model 更大所以以后看到模型配置里的:
num_hidden_layers hidden_size num_attention_heads就知道这些并不只是 AI 算法工程师才需要看的东西。
它们最终都会影响:
参数数量 模型文件大小 显存 计算量也就是 Infra。
八、但 Transformer 并不能直接读懂一句中文
现在模型已经有了:
Transformer + 几亿个 Parameter假设用户输入:
请解释一下什么是 AI Infra。能不能直接把这句话送进 GPU?
当然不行。
因为前面几篇已经知道,GPU 真正处理的是:
Tensor里面是:
Number不是:
中文 英文 标点符号所以文字进入模型以前,还需要经过另外一个非常重要的组件:
Tokenizer九、Tokenizer:把人类文字转换成模型能够处理的 Token
Tokenizer 可以先简单理解成:
Text ↓ Tokenizer ↓ Token ↓ Token ID例如:
AI Infra 到底是什么?经过 Tokenizer 以后,可能变成若干:
Token然后每个 Token 再对应一个整数:
[xxxx, xxxx, xxxx, xxxx, ...]真正送给 PyTorch Model 的,最后其实是一组类似:
input_ids的 Tensor。
所以现在数据链路变成:
人类文字 "AI Infra 到底是什么?" ↓ Tokenizer ↓ Token IDs ↓ PyTorch Tensor ↓ Model这时突然会发现:
Tokenizer 其实是连接“人类语言世界”和“Tensor 世界”的那座桥。
十、Token 并不等于一个字,也不等于一个单词
这是大模型里面特别容易误解的一件事。
我们经常看到:
100 Tokens 1000 Tokens 32K Context 128K Context于是很容易把:
Token理解成:
一个汉字或者:
一个英文单词其实都不准确。
不同 Tokenizer 会按照自己的词表和规则拆分文字。
所以:
字符数 ≠ 单词数 ≠ Token 数例如:
AI Infrastructure可能被拆成多个 Token。
中文一句话也可能按照汉字、词语或者其他子词方式拆分。
对于 Infra 来说,真正值得关注的是:
最终产生了多少 Token因为以后很多东西都会围绕 Token 来讨论。
这一篇暂时先记住:
LLM 处理文字时,最基本的输入单位不是“字数”,而是 Token。
十一、Prompt 和 Context 又是什么?
这两个词也经常一起出现。
Prompt
可以先理解成:
我们送给模型的输入。
例如:
请用三句话解释什么是 Kubernetes。就是一个简单 Prompt。
但真正的聊天系统中,送给模型的内容可能不只有用户这一句话。
还可能包括:
System Prompt 聊天历史 用户当前问题 其他额外信息这些内容最后会被组合起来。
Context
模型这一次能够看到的完整 Token 序列,可以粗略理解成:
Context例如:
System Prompt + History + Current Prompt经过 Tokenizer:
↓ Token Token Token ...这些共同构成模型当前的 Context。
于是:
Prompt更偏向:
给模型的输入内容而:
Context更偏向:
模型这一次真正能够参考的整个 Token 上下文以后我们还会不断看到:
Context Window例如:
32K 128K这表示模型能够处理的上下文 Token 数存在一定范围。
至于:
Context 越长 为什么显存增加? 为什么速度下降?这些就已经属于下一篇的推理运行问题了。
这一篇先不展开。
十二、现在把一个 LLM 从 Infra 角度完整画出来
到这里,可以画出这一篇最重要的一张图:
LLM │ ┌─────────┴─────────┐ │ │ ▼ ▼ Model Structure Tokenizer │ │ │ │ ▼ ▼ Transformer Text → Token │ │ │ ▼ │ Token IDs │ │ │ │ ├───────────────────┘ │ ▼ Model Parameters │ ▼ Weight Tensors │ ▼ PyTorch │ ▼ GPU VRAM如果再加入模型文件:
Model Repository │ ├── config.json │ ↓ │ Model Structure │ ├── tokenizer.json │ ↓ │ Tokenizer │ └── model.safetensors ↓ Parameters ↓ Weight Tensor ↓ System RAM ↓ PCIe ↓ GPU VRAM这就是这一篇真正想建立的:
LLM Infra 第一张完整地图。
十三、实验环境
实验机器继续沿用前几篇:
Ubuntu 24.04 Server Intel Core i5-10400F 16GB RAM NVIDIA GeForce RTX 3060 12GB前面已经完成:
NVIDIA Driver CUDA PyTorch GPU Tensor验证。
所以这一篇不再重新检查:
lspci nvidia-smi nvcc torch.cuda.is_available()那些内容。
直接继续增加:
Transformers + Model实验使用一个比较小的模型:
Qwen/Qwen2.5-0.5B-Instruct原因很简单。
这一篇不是比较模型能力。
而是观察:
Tokenizer Parameter Model Loading RAM VRAM所以小模型反而更加适合实验:
下载快 加载快 显存压力小 现象又足够完整RTX 3060 12GB 运行这种规模的模型也比较轻松。
十四、实验一:安装 Transformers
继续进入上一篇的 Python Virtual Environment:
cd ~/ai-infra-lab source .venv/bin/activate安装:
pip install -U transformers accelerate safetensors检查:
python -c "import transformers; print(transformers.__version__)"现在我们的软件栈继续向上增加了一层:
Application ↓ Transformers ↓ PyTorch ↓ CUDA ↓ NVIDIA Driver ↓ RTX 3060这里顺便注意两个名字:
Transformer和:
Transformers不是一回事。
前者:
Transformer是模型架构。
后者:
Transformers是 Hugging Face 提供的 Python Library。
十五、实验二:先看看 Tokenizer 到底干了什么
先不加载模型。
创建:
nano tokenizer_test.py写入:
from transformers import AutoTokenizer MODEL_ID = "Qwen/Qwen2.5-0.5B-Instruct" tokenizer = AutoTokenizer.from_pretrained( MODEL_ID ) text = "从 Infra 角度看,大语言模型到底是什么?" inputs = tokenizer( text, return_tensors="pt" ) print("Text:") print(text) print() print("Input IDs:") print(inputs["input_ids"]) print() print( "Token Count:", inputs["input_ids"].shape[-1] ) print() print("Tokens:") print( tokenizer.convert_ids_to_tokens( inputs["input_ids"][0] ) )运行:
python tokenizer_test.py重点不是记住那些 Token ID。
而是观察:
自然语言 ↓ Tokenizer ↓ Token ↓ Integer ID ↓ PyTorch Tensor可以继续修改:
Hello World AI Infrastructure 人工智能基础设施 Kubernetes 为什么需要 Scheduler?然后观察:
字符串长度和:
Token Count并不是简单的一一对应。
这一小段实验以后还会反复使用。
因为到了真正的 LLM Infra:
多少 Token会比:
多少字重要得多。
十六、实验三:真正把一个 Model 加载出来
接下来进入这一篇最重要的实验。
创建:
nano load_model.py写入:
import torch from transformers import ( AutoModelForCausalLM, AutoTokenizer, ) MODEL_ID = "Qwen/Qwen2.5-0.5B-Instruct" def mib(value): return value / 1024**2 def show_gpu_memory(title): print() print(f"=== {title} ===") print( "Allocated:", f"{mib(torch.cuda.memory_allocated()):.1f} MiB" ) print( "Reserved :", f"{mib(torch.cuda.memory_reserved()):.1f} MiB" ) print( "GPU:", torch.cuda.get_device_name(0) ) show_gpu_memory("Before Model Loading") print() print("Loading Tokenizer...") tokenizer = AutoTokenizer.from_pretrained( MODEL_ID ) print() print("Loading Model to CPU RAM...") model = AutoModelForCausalLM.from_pretrained( MODEL_ID, dtype=torch.float16, low_cpu_mem_usage=True, ) model.eval() parameter_count = sum( p.numel() for p in model.parameters() ) parameter_bytes = sum( p.numel() * p.element_size() for p in model.parameters() ) print() print( "Parameter Count:", f"{parameter_count:,}" ) print( "Parameter Memory:", f"{parameter_bytes / 1024**3:.3f} GiB" ) print( "Model dtype:", next(model.parameters()).dtype ) print( "Model device:", next(model.parameters()).device ) show_gpu_memory("Model on CPU") print() print("Moving Model to GPU...") model.to("cuda") torch.cuda.synchronize() print( "Model device:", next(model.parameters()).device ) show_gpu_memory("Model on GPU") input( "\nPress Enter to exit..." )运行:
python load_model.py最后程序会暂停。
这样就有时间在另一个 Terminal 中观察:
nvidia-smi甚至可以一直:
watch -n 0.5 nvidia-smi十七、这次应该观察哪些数据?
这一篇不要只看一句:
Model loaded successfully真正值得记录的是下面几组数据。
首先:
Parameter Count看看实际模型到底有多少参数。
然后看:
Model dtype这次我们明确选择:
float16再看:
Parameter Memory理论上它应该和:
Parameter Count × 2 Bytes处在相近量级。
于是:
参数数量 ↓ dtype ↓ 理论 Weight Size第一次可以和真实模型对应起来。
十八、最重要的观察:Model 在 CPU 和 GPU 是两个状态
代码刚执行:
AutoModelForCausalLM.from_pretrained(...)的时候:
Model其实已经存在了。
但:
next(model.parameters()).device应该仍然显示:
cpu这意味着:
Model File ↓ PyTorch Model ↓ System RAM模型虽然加载了:
但还没有进入 GPU。
接下来执行:
model.to("cuda")以后:
device变成:
cuda:0与此同时:
nvidia-smi里的显存也会明显增加。
于是模型真正完成:
Model File ↓ System RAM ↓ PyTorch Parameter Tensor ↓ PCIe ↓ GPU VRAM这就是上一篇:
tensor.to("cuda")的进一步放大。
上一篇搬过去的是一个普通 Tensor。
这一篇搬过去的是:
组成整个 LLM 的几亿个 Parameter。
十九、这里终于可以解释“模型占显存”是什么意思
我们经常说:
这个模型需要多少显存?以前听起来好像是某种特殊的大模型机制。
现在已经可以拆开理解。
当:
model.to("cuda")以后,模型中的大量:
Parameter Tensor全部需要拥有自己的:
GPU Memory所以首先可以近似认为:
Model Weight VRAM ≈ Parameter Count × Parameter dtype例如:
0.5B × FP16大约就是:
1GB 量级而:
7B × FP16就是:
14GB 量级到这里:
0.5B 7B FP16 VRAM几个原本看起来完全不同的词,终于被一条线连接起来了。
二十、建议记录一张自己的实验表
我建议把自己的真实结果填进去。
这是我的结果:
| 项目 | 实测结果 |
|---|---|
| Model | Qwen2.5-0.5B-Instruct |
| Parameter Count | 494,032,768 |
| dtype | FP16 |
| 理论 Parameter Memory | 0.920 GiB |
| Model 在 CPU 时 GPU Allocated | 1 MiB |
| Model 进入 GPU 后 Allocated | 950.2 MiB |
nvidia-smi显存 | 1105 MiB |
另外还可以补一张:
free -h在:
模型加载前模型加载到 CPU 后的对比。
这样就能真正看到:
Model File ↓ System RAM ↓ GPU VRAM整个资源变化过程。
这里同样不建议提前写死某个显存数字。
因为:
PyTorch Version Transformers Version CUDA Context Caching Allocator都会带来一定差异。
真正应该观察的是:
资源变化的方向和数量级。
注意:本篇实验代码也可通过命令获取
git clone https://github.com/mosesyyoung/ai-infra-lab.git二十一、几个这一篇特别值得注意的坑
1. 第一次加载模型很慢,不一定是模型加载慢
第一次运行:
from_pretrained(...)很可能还在下载:
config tokenizer model weights因此:
Download Time和:
Model Loading Time不要混在一起。
后面如果要测试模型加载速度,应该先让模型完整缓存到本地。
2. Tokenizer 加载了,不代表 Model 也加载了
AutoTokenizer.from_pretrained(...)主要是在加载:
Tokenizer并没有把几亿个模型参数放进 GPU。
所以运行 Tokenizer 时:
GPU VRAM一般不会因为模型权重而大幅增加。
3.from_pretrained()和model.to("cuda")不是一回事
这是这一篇非常值得记住的一点。
from_pretrained(...)首先完成:
Model File ↓ PyTorch Model而:
model.to("cuda")才真正完成:
Parameter ↓ GPU VRAM以后遇到:
CPU Offload Device Map Multi-GPU本质上仍然是在研究:
这些 Parameter 到底应该放在哪里。
4. 模型文件 1GB,不代表nvidia-smi必须刚好增加 1GB
因为 GPU 进程除了:
Model Weight还可能有:
CUDA Context PyTorch Runtime Caching Allocator Temporary Buffer所以:
模型文件大小和:
nvidia-smi Used Memory不应该要求完全相等。
上一篇我们已经知道:
memory_allocated memory_reserved nvidia-smi本身就是不同视角。
这一篇重点看:
Model 进入 GPU 前和:
Model 进入 GPU 后的变化即可。
5. 0.5B 不等于 0.5GB
这是一个很容易产生的误会。
0.5B表示:
大约 5 亿参数不是模型文件大小。
模型实际大小还取决于:
dtype 量化方式 保存格式例如同样的 Parameter Count:
FP32 FP16 INT8 INT4最终需要的存储空间可能完全不同。
量化我们后面再专门研究。
6. Context Length 不是模型文件大小
例如看到:
32K Context它描述的是:
模型能够处理多长的 Token 上下文不是:
模型拥有 32K 参数也不是:
模型文件有 32KB它属于模型运行时输入能力的一部分。
至于为什么 Context 越长会影响显存和速度,下一篇再真正解释。
7. Wi-Fi 下载大模型时 SSH 频繁断开:检查 Power Save
如果实验机通过 Wi-Fi 连接网络,在下载较大的模型文件时,偶尔可能遇到 SSH 会话突然断开的情况。
这次我的现象就是:平时 SSH 基本正常,但 Hugging Face 持续下载近 1GB 模型文件时,连接频繁中断。最后发现无线网卡开启了 Power Save。
以实验机无线网卡连接 wlp2s0 为例,先检查:
iw dev wlp2s0 get power_save如果看到:
Power save: on可以先临时关闭验证:
sudo iw dev wlp2s0 set power_save off再次检查:
iw dev wlp2s0 get power_save如果变成:
Power save: off并且 SSH 和模型下载恢复稳定,就可以考虑永久关闭。
我的 Ubuntu Server 使用下面的 systemd Service:
sudo nano /etc/systemd/system/wifi-powersave-off.service写入:
[Unit] Description=Disable WiFi power saving on wlp2s0 After=network.target [Service] Type=oneshot ExecStart=/usr/sbin/iw dev wlp2s0 set power_save off RemainAfterExit=yes [Install] WantedBy=multi-user.target然后启用:
sudo systemctl daemon-reload sudo systemctl enable --now wifi-powersave-off.service重启后再确认:
iw dev wlp2s0 get power_save仍然显示Power save: off即可。
当然,这个问题只针对使用 Wi-Fi 的实验机。如果使用稳定的有线网络,可以直接跳过这一项。这里真正值得记住的是:下载大模型这种持续网络负载,有时会把平时不明显的网络稳定性问题暴露出来,不要一看到 SSH 断开就先怀疑 PyTorch、GPU 或模型本身。
二十二、现在重新看一个 LLM,它已经没那么神秘了
在这一篇以前,一个大模型可能只是:
Prompt ↓ LLM ↓ Answer中间整个:
LLM都是黑盒。
现在可以把它展开:
LLM │ ┌─────────────┼─────────────┐ │ │ │ ▼ ▼ ▼ Config Tokenizer Weights │ │ │ ▼ ▼ ▼ Transformer Token Parameter Architecture │ │ │ ▼ ▼ │ Token IDs Weight Tensor │ │ │ └─────────────┴──────┬──────┘ │ ▼ PyTorch │ ▼ GPU VRAM从 Infra 角度来看,一个已经训练好的 LLM 最重要的几样东西其实就是:
Architecture Parameters Tokenizer Context而我们今天真正亲手验证的是:
Model File ↓ Parameters ↓ PyTorch Tensor ↓ System RAM ↓ GPU VRAM这一条链。
二十三、总结
这一篇,我们终于从:
PyTorch真正进入:
Model这一层。
最值得记住的几个概念是:
Parameter Weight Tokenizer Token Transformer Prompt Context第一:
所谓 0.5B、7B、70B,首先描述的是模型 Parameter 的数量。
第二:
模型 Parameter 最终仍然是 Tensor。
所以前面学过的:
shape dtype device到了 Model 依然成立。
第三:
Parameter Count × dtype,可以粗略估算模型 Weight 需要多少空间。
例如:
7B × FP16 ≈ 14GB终于有了完整含义。
第四:
Tokenizer 是人类文字进入模型之前必须经过的一层。
真正进入模型的是:
Token IDs而不是字符串本身。
第五:
Model Loading 和 Model 进入 GPU 不是同一个动作。
可以简单分成:
Model File ↓ System RAM以及:
System RAM ↓ PCIe ↓ GPU VRAM两个阶段。
第六:
模型权重是 LLM 显存里最基础、最稳定的一块长期资源。
至于真正执行请求以后,显存里还会出现什么,我们还没有展开。
这恰好就是下一篇的问题。
二十四、下一篇为什么自然会出现 Prefill 和 Decode?
到现在,我们已经完成:
GPU ↓ CUDA ↓ PyTorch ↓ LLM模型终于真正躺在:
GPU VRAM里了。
但我们还没有认真研究:
当一个 Prompt 真正送进这个模型以后,到底发生了什么?
例如:
请解释一下什么是 AI Infra。经过:
Tokenizer以后变成几十个 Token。
接下来呢?
为什么模型不是一次把整个答案算出来?
为什么 ChatGPT、Qwen 这些模型回答问题时,看起来都是:
一个 Token ↓ 一个 Token ↓ 再一个 Token不断往外生成?
Prompt 越长,为什么第一个字往往等得越久?
一次请求为什么还会继续增加显存?
模型明明已经全部放在 GPU 里了:
新的显存又是谁占掉的?
于是下一步,我们终于要把:
Inference真正打开。