dask仅适用于单机可加载模型但输入数据远超内存的批量推理场景,而非分布式加载超大模型;其核心是用dask.delayed封装独立加载与推理函数,按数据分片调度,需严格管控gpu资源与序列化。

Dask 本身不用于“加载超大模型”——它不替代 torch.load 或 transformers.AutoModel.from_pretrained,也不直接支持模型参数的分布式加载或推理。如果你正卡在“模型太大、单机显存/内存爆掉”,用 dask 硬上反而会加重负担甚至失败。
真正该做的,是分清场景:
- 想训练/微调超大模型?→ 用
DeepSpeed、FSDP、Accelerate - 想做超大数据上的模型推理(比如批量跑百万条文本)?→
dask才有用武之地
下面按实际可落地的路径说清楚。
什么时候该用 dask 做模型推理?
只在以下情况成立:模型能单机加载(比如 10GB 模型进得去 GPU),但输入数据远超内存(比如 100GB 文本要逐条 infer)。这时 dask 的价值是切分数据、调度批处理、避免一次性读入全量。
- 典型场景:用
bert-base-chinese对千万级 CSV 中的text列批量提取句向量 - 错误用法:试图用
dask.delayed把AutoModel.from_pretrained("llama3-70b")拆开加载 → 失败,因为模型权重无法跨任务分割 - 关键前提:模型必须能在单 worker 上完整加载(即单卡/单机资源够),
dask只管数据流
怎么用 dask 安全调度模型推理?
核心原则:每个 dask worker 独立加载模型(不能共享模型实例),靠序列化输入/输出通信。否则会遇到 PicklingError 或 CUDA context 冲突。
- 必须用
dask.delayed封装整个推理函数,而不是只包裹model(input) - 模型加载放在函数内部(每次 worker 调用时加载一次),或用模块级缓存(配合
if not hasattr(...)防重复) - 输入数据必须是
dask.bag或dask.delayed构建的惰性序列,不能是 pandas DataFrame 全量读入 - 示例片段:
import dask from transformers import AutoTokenizer, AutoModel <p>@dask.delayed def infer_batch(texts):</p><h1>每次调用都独立加载(小模型可接受)或加缓存</h1><pre class="brush:python;toolbar:false;">tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese") model = AutoModel.from_pretrained("bert-base-chinese").cuda() inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt").to("cuda") with torch.no_grad(): outputs = model(**inputs) return outputs.last_hidden_state.mean(dim=1).cpu().numpy()假设 texts_bag 是 dask.bag.from_sequence([...], partition_size=1000)
results = [infer_batch(chunk) for chunk in texts_bag.to_delayed()] dask.compute(*results)
为什么 dask.distributed.Client 容易崩?
不是代码写错,而是资源没对齐。常见死因:
-
Client(n_workers=8)却没限制每个 worker 的 GPU 显存 → 8 个 worker 同时加载模型,显存直接 OOM - worker 启动时没指定
CUDA_VISIBLE_DEVICES→ 所有 worker 争抢同一张卡 - 没关掉模型的
torch.compile或flash attention→ 初始化耗时长,触发 worker heartbeat timeout - 解决方案:
- 启动 client 时强制绑定 GPU:
Client(n_workers=4, threads_per_worker=1, memory_limit="8GB", dashboard_address=None) - worker 启动前设置环境变量:
os.environ["CUDA_VISIBLE_DEVICES"] = str(worker_id % 4)(需自定义 worker 初始化) - 推理函数开头加
torch.cuda.empty_cache(),结尾加del model, tokenizer
- 启动 client 时强制绑定 GPU:
比 dask 更省事的替代方案?
如果只是跑 batch inference,dask 的调度复杂度常被低估。更轻量的选择:
-
joblib.Parallel+n_jobs:适合 CPU 推理,无 GPU 管理负担 -
torch.utils.data.DataLoader+num_workers > 0:原生支持多进程预加载,且能复用模型实例(通过worker_init_fn加载) -
ray:API 更简洁,@ray.remote自动处理序列化和资源隔离,对 GPU worker 支持更透明 - 真超大模型(>20B)?别碰
dask—— 直接切到vLLM或TGI提供的 HTTP 批量接口,用requests+asyncio并发调用
dask 的边界很清晰:它擅长“把大任务拆成小任务扔给多机”,但绝不负责“把大模型拆开”。搞混这点,调试三天也跑不通。模型加载、显存分配、CUDA context 管理,全得自己兜底。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











